C# duck-typing to the rescue for Interface Segregation
Interfaces are the method by which we get multiple inheritance in C#, Java, etc. They are contracts without implementation. We don't get the messy resolution of which code to use from multiple base classes, because there's only one inheritance chain that includes code.
They're useful to let us provide one contract and multiple implementations or simply describe a contract for our code and allow someone else to come along and replace our implementation entirely.
In practice, though, I almost always use them purely for decoupling the contract from the code, so that I can replace the implementation with a mock version in unit tests. Hmm.. So, I use interfaces just to get around the yoke of the type system? Wait, why I am so in love with statically typed languages again?
Right... While the above sounds like the interface exists just so that I can mock my implementation, the real purpose of the interface is the ability for the consuming code to express a contract for its dependencies. It's unfortunate that interface implementation forces them to be attached at the implementation side, which is why I say that Interface attachment is upside down. And it's deep rooted in the language, after all it's called Interface Inheritance not Dependency Contract Definition.
So, it's not surprising that there is no CLR-level way around this limitation. Fortunately, you can always create a dynamic proxy that wraps your class and implements the Interface. Both Castle's
DynamicProxy and LinFu's
DynamicProxy are excellent frameworks for writing your own proxies. I've never tested them against each other, but have used both in production and neither showed up as culprits when time for profiling came about.
With a dynamic proxy, you can generate an object that claims to implement an interface but under the hood just has a interceptors that provide the call signature to let you respond correctly or proxy the call on to a class you are wrapping. I've previously covered how you can even use them to have a class inherit from more than one base class via a proxy. This is necessary if you want to remote an object, which requires a base of
MarshalByRefObject, but you already have a base class.
However, proxies require a fair bit of hand-rolling so they are not the most lightweight way, development time wise, to attach an Interface.
What would be really useful would be the ability to cast an object to an interface:
The above code would even be compile time verifiable, since we can simply see if the
User implements the call signatures promised by
IUser. This would be provide us strongly typed Duck Typing -- an object that can quack ought to be able to be treated as a duck.
This is where LinFu goes a step further than just
DynamicProxy and provides duck typing as well:
DynamicObject's constructor takes an instance of a class to wrap. You can then create a duck from that dynamic object which automatically proxies the given interface and will call the appropriate method on the wrapped class on demand.
Using duck typing to satisfy the Interface Segregation Principle
Saying that you may have a class that has the perfect method signature but doesn't implement an interface you already have, does sound rather contrived. However, forcing a class to implement an interface of your choosing does have some real benefits, aside from being able to abstract an existing class into a mockable dependency:
One problem with interfaces is that they tell you everything an implementation can do. And often a class acts as a service that provides functionality to more than one client class, but provides just a single interface. That single interface may expose capabilities that you don't care about.
Instead, interfaces should be fine-grained to only include the methods appropriate to the client. But that's not always feasible. Aside from having a class implement lots of tiny interfaces, the service class does not know about the client's requirements, so it really doesn't know what the interfaces should include. The client, on the other hand, does know and can tailor exactly the right interface it wants as a contract with the dependency.
Suppose we have message queue for passing data between decoupled classes:
Proper interface segregation would have us create a Dispatcher interface for our message Producer
and an inbox interface for our message Consumer
MessageQueue does not implement our interfaces (yes, in this case it would not have been a problem to have the class implement them both, but this is a simplified example with obvious segregation lines), we can now configure our IoC container (example uses AutoFac) to create the appropriately configured IProducer and IConsumer, each receiving exactly those capabilities they should depend on:
var queue = new MessageQueue();
var builder = new ContainerBuilder();
builder.Register(c => new DynamicObject(queue).CreateDuck<IMessageDispatcher>()).As<IMessageDispatcher>();
builder.Register(c => new DynamicObject(queue).CreateDuck<IMessageBox>()).As<IMessageBox>();
using (var container = builder.Build())
var producer = container.Resolve<IProducer>();
var consumer = container.Resolve<IConsumer>();
But what about C# 4.0 & Dynamic
While I think Dynamic objects in C# 4.0 are very cool, as of right now, they seem to have skipped over duck typing, at least in a strongly typed fashion.
Sure, once you have a dynamic instance, the compiler will let you call whatever signature you wish on it and defers checking until execution time. But that means we have no contract on it, if used as a dependency, nor can we use it to dynamically create objects that provide implementations for existing contracts. So, you've have to wrap a dynamic object with a proxy, in which case, LinFu's existing duck typing already provides a superior solution.
The lack of casting to an interface, imho was already oversight with C# 3.0, which introduced anonymous classes that are so convenient for Linq projections, but can't be passed out of the scope of the current method, due to a lack of type.
So don't expect C# 4.0 to do anything to let you more easily attach your contracts at the dependency level. For the foreseeable future, this remains the territory of Dynamic Proxy.
Next time: Delegate injection
However, there is another way to deal with dependency injection that provides a fine-grained contract and imposes no proxies nor other requirement on the classes providing the dependency: Injection of the required capabilities as delegates
I've been experimenting with a framework to make this as painless as traditional IoC containers make dependency resolution. It's still a bit rough around the edges, but I hope to have some examples to write about soon.