When building large scale applications a very useful design pattern to adopt is dependency injection. An example of this is programming to interfaces such that the implementation of each interface can be interchanged.
In this post I will demonstrate some examples of how you can go about adding functionality to interfaces with extension methods.
Consider the following example with some demo interfaces and classes:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 |
//Incident is a simple dto which could include things like category, severity, message, date etc public class Incident { public string Message { get; set; } public Severity IncidentSeverity { get; set; } } //Incident severity public enum Severity { Info, Warn, Fatal } //Interface for our logging public interface ILog { //Write incident to log void Write(Incident incident); } //Implementation of our log - behind the scenes this could log to any format public class Log : ILog { public void Write(Incident incident) { //write to required log eg sql / xml } } public class MyProgram { public void DoSomething() { //perform tasks //access instance of log //note: DependencyInjectionLogic.Instantiate is //pseudo code for this, libraries are available to perform this kind of operation //the idea being that Log is the selected implementation ILog log = DependencyInjectionLogic.Instantiate<ILog>(); log.Write(new Incident() { IncidentSeverity = Severity.Info, Message = "Message" }); } } |
This is all well and good – the user can write log entries with the following line:
1 |
log.Write(new Incident() { IncidentSeverity = Severity.Info, Message = "Message" }); |
So, how can we achieve:
1 |
ILog.Warn("message"); |
The interface cannot contain any implementation. One solution would be to use abstract classes for the base class however that goes against the principal of programming to interfaces.
How about extension methods? Using the following examples we can add these shorthand methods to our ILog hiding some of the complexity / repeated code:
1 2 3 4 5 6 7 8 9 10 11 12 13 |
public static class ILogExtensions { public static void Warn(this ILog log, string message) { Incident incident = new Incident() { IncidentSeverity = Severity.Warn, Message = message }; log.Write(incident); } } |
If you setup the extension methods in the same namespace as your interface, you will now have available:
1 |
ILog.Warn("message"); |