Mixins in .NET
Mixins are a good way to weave functionality into a class. Wikipedia defines Mixin as follows
“In object-oriented programming languages, a mixin is a class that provides a certain functionality to be inherited by a subclass, while not meant for instantiation (the generation of objects of that class). Inheriting from a mixin is not a form of specialization but is rather a means of collecting functionality. A class may inherit most or all of its functionality from one or more mixins through multiple inheritance.”
Nice languages have mixins as part of the language spec. Ruby, for example, supports mixins through the notion of Modules , a way to group in related methods (and classes and constants) which is not a class in itself . You can program a bit of logic that interacts with the class it is hosted in, effectively letting you get multiple-inheritance in a decent manner. For example Ruby has a Comparable mixin which requires you implement a <=> method telling it what to compare, and you get all the comparing operators (<,<=,==..)
1 2 3 4 5 6 | <span style="color:#9966CC; font-weight:bold;">class</span> Car
<span style="color:#9966CC; font-weight:bold;">include</span> <span style="color:#CC00FF; font-weight:bold;">Comparable</span>
<span style="color:#9966CC; font-weight:bold;">def</span> <span style="color:#006600; font-weight:bold;"><=></span><span style="color:#006600; font-weight:bold;">(</span>other<span style="color:#006600; font-weight:bold;">)</span>
<span style="color:#0000FF; font-weight:bold;">self</span>.<span style="color:#9900CC;">year</span> <span style="color:#006600; font-weight:bold;"><=></span> other.<span style="color:#9900CC;">year</span>
<span style="color:#9966CC; font-weight:bold;">end</span>
<span style="color:#9966CC; font-weight:bold;">end</span> |
Compare that (sorry for the pun) to C# where you need to inherit an interface and implement all the code yourself. If we had a similar Car class in C# and we’d want to sort it by year we’d have to implement IComparer.Compare() method (per the example from KB320277 “How to use the IComparable and IComparer interfaces in Visual C#”
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | <span style="color: #0600FF;">private</span> <span style="color: #FF0000;">class</span> sortYearAscendingHelper <span style="color: #008000;">:</span> IComparer
<span style="color: #000000;">{</span>
<span style="color: #FF0000;">int</span> IComparer.<span style="color: #0000FF;">Compare</span><span style="color: #000000;">(</span><span style="color: #FF0000;">object</span> a, <span style="color: #FF0000;">object</span> b<span style="color: #000000;">)</span>
<span style="color: #000000;">{</span>
car c1<span style="color: #008000;">=</span><span style="color: #000000;">(</span>car<span style="color: #000000;">)</span>a<span style="color: #008000;">;</span>
car c2<span style="color: #008000;">=</span><span style="color: #000000;">(</span>car<span style="color: #000000;">)</span>b<span style="color: #008000;">;</span>
<span style="color: #0600FF;">if</span> <span style="color: #000000;">(</span>c1.<span style="color: #0000FF;">year</span> <span style="color: #008000;">></span> c2.<span style="color: #0000FF;">year</span><span style="color: #000000;">)</span>
<span style="color: #0600FF;">return</span> <span style="color: #FF0000;">1</span><span style="color: #008000;">;</span>
<span style="color: #0600FF;">if</span> <span style="color: #000000;">(</span>c1.<span style="color: #0000FF;">year</span> <span style="color: #008000;"><</span> c2.<span style="color: #0000FF;">year</span><span style="color: #000000;">)</span>
<span style="color: #0600FF;">return</span> <span style="color: #008000;">-</span><span style="color: #FF0000;">1</span><span style="color: #008000;">;</span>
<span style="color: #0600FF;">else</span>
<span style="color: #0600FF;">return</span> <span style="color: #FF0000;">0</span><span style="color: #008000;">;</span>
<span style="color: #000000;">}</span>
<span style="color: #000000;">}</span> |
Actually C# has a weak notion of Modules which is called Static Classes and Extension method. It is weak since the the extension methods (and other methods in the static classes) need to be static which is limiting. In many cases though combining interfaces with extension methods gets you a reasonable mixin effect.
For example in my current project we have profiling events that bubble up e.g. the profiling run completed – that would mean the class would implement the ISignalEndOfRun interface which inherits the ImProfilingEvent interface.
Then I have some code that holds handlers (implementing an ImHandler interface) and passes the events to the handlers
1 2 3 4 5 6 7 8 | <span style="color: #0600FF;">private</span> List<span style="color: #008000;"><</span>ImHandler<span style="color: #008000;">></span> handlers <span style="color: #008000;">=</span> <span style="color: #008000;">new</span> List<span style="color: #008000;"><</span>ImHandler<span style="color: #008000;">></span><span style="color: #000000;">(</span><span style="color: #000000;">)</span><span style="color: #008000;">;</span>
<span style="color: #0600FF;">public</span> <span style="color: #0600FF;">void</span> HandleEvnet<span style="color: #000000;">(</span>ImProfilingEvent profilingEvent<span style="color: #000000;">)</span>
<span style="color: #000000;">{</span>
<span style="color: #0600FF;">foreach</span> <span style="color: #000000;">(</span>var handler <span style="color: #0600FF;">in</span> handlers<span style="color: #000000;">)</span>
<span style="color: #000000;">{</span>
handler.<span style="color: #0000FF;">Handle</span><span style="color: #000000;">(</span>profilingEvent<span style="color: #000000;">)</span><span style="color: #008000;">;</span>
<span style="color: #000000;">}</span>
<span style="color: #000000;">}</span> |
And I want only the handlers that actually handle the specific event to do so. I also want to keep the handlers clean so a handler would look something like:
1 2 3 4 5 6 7 | <span style="color: #0600FF;">internal</span> <span style="color: #FF0000;">class</span> SomeHandler <span style="color: #008000;">:</span> IHandle<span style="color: #008000;"><</span>ISignalEndOfRun<span style="color: #008000;">></span>
<span style="color: #000000;">{</span>
<span style="color: #0600FF;">public</span> <span style="color: #0600FF;">void</span> Handle<span style="color: #000000;">(</span>ISignalEndOfRun evt<span style="color: #000000;">)</span>
<span style="color: #000000;">{</span>
<span style="color: #008080; font-style: italic;">//Do something</span>
<span style="color: #000000;">}</span>
<span style="color: #000000;">}</span> |
And I can do that and have everything wired and working correctly if I make the IHandle interface a mixin. Here’s what it looks like:
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 | <span style="color: #0600FF;">public</span> <span style="color: #FF0000;">interface</span> ImHandler
<span style="color: #000000;">{</span>
IEnumerable<span style="color: #008000;"><</span>Result<span style="color: #008000;">></span> GetResults<span style="color: #000000;">(</span><span style="color: #000000;">)</span><span style="color: #008000;">;</span>
<span style="color: #000000;">}</span>
<span style="color: #0600FF;">public</span> <span style="color: #FF0000;">interface</span> IHandle<span style="color: #008000;"><</span><span style="color: #0600FF;">in</span> TProfilingEvent<span style="color: #008000;">></span> <span style="color: #008000;">:</span> ImHandler where TProfilingEvent<span style="color: #008000;">:</span>ImProfilingEvent
<span style="color: #000000;">{</span>
<span style="color: #0600FF;">void</span> Handle<span style="color: #000000;">(</span>TProfilingEvent evt<span style="color: #000000;">)</span><span style="color: #008000;">;</span>
<span style="color: #000000;">}</span>
<span style="color: #0600FF;">internal</span> <span style="color: #0600FF;">static</span> <span style="color: #FF0000;">class</span> HandlerExtensions
<span style="color: #000000;">{</span>
<span style="color: #0600FF;">public</span> <span style="color: #0600FF;">static</span> <span style="color: #0600FF;">void</span> Handle<span style="color: #000000;">(</span><span style="color: #0600FF;">this</span> ImHandler handler, ImProfilingEvent profilingEvent<span style="color: #000000;">)</span>
<span style="color: #000000;">{</span>
var handlerInterfaces <span style="color: #008000;">=</span> <span style="color: #008080; font-style: italic;">/* Find the generic IHandle<> interfaces of the handler */</span>
handler.<span style="color: #0000FF;">GetType</span><span style="color: #000000;">(</span><span style="color: #000000;">)</span>.<span style="color: #0000FF;">GetInterfaces</span><span style="color: #000000;">(</span><span style="color: #000000;">)</span>.<span style="color: #0000FF;">Where</span><span style="color: #000000;">(</span>
i <span style="color: #008000;">=></span> i.<span style="color: #0000FF;">IsGenericType</span> <span style="color: #008000;">&&</span> i.<span style="color: #0000FF;">GetGenericTypeDefinition</span><span style="color: #000000;">(</span><span style="color: #000000;">)</span> <span style="color: #008000;">==</span> <span style="color: #008000;">typeof</span><span style="color: #000000;">(</span>IHandle<span style="color: #008000;"><></span><span style="color: #000000;">)</span><span style="color: #000000;">)</span><span style="color: #008000;">;</span>
<span style="color: #0600FF;">if</span> <span style="color: #000000;">(</span>handlerInterfaces.<span style="color: #0000FF;">Count</span><span style="color: #000000;">(</span><span style="color: #000000;">)</span> <span style="color: #008000;">==</span> <span style="color: #FF0000;">0</span><span style="color: #000000;">)</span> return<span style="color: #008000;">;</span>
var profilerEventInterfaces <span style="color: #008000;">=</span> FindProfileEventinterface<span style="color: #000000;">(</span>profilingEvent, handlerInterfaces<span style="color: #000000;">)</span><span style="color: #008000;">;</span>
<span style="color: #0600FF;">foreach</span> <span style="color: #000000;">(</span>var handlerInterface <span style="color: #0600FF;">in</span> handlerInterfaces<span style="color: #000000;">)</span>
<span style="color: #000000;">{</span>
<span style="color: #0600FF;">if</span> <span style="color: #000000;">(</span>handlerInterface.<span style="color: #0000FF;">GetGenericArguments</span><span style="color: #000000;">(</span><span style="color: #000000;">)</span>.<span style="color: #0000FF;">First</span><span style="color: #000000;">(</span><span style="color: #000000;">)</span> <span style="color: #008000;">==</span> profilerEventInterfaces<span style="color: #000000;">)</span>
<span style="color: #000000;">{</span>
var method <span style="color: #008000;">=</span> handlerInterface.<span style="color: #0000FF;">GetMethod</span><span style="color: #000000;">(</span><span style="color: #666666;">"Handle"</span><span style="color: #000000;">)</span><span style="color: #008000;">;</span>
var param <span style="color: #008000;">=</span> <span style="color: #008000;">new</span> <span style="color: #FF0000;">object</span><span style="color: #000000;">[</span><span style="color: #000000;">]</span> <span style="color: #000000;">{</span> profilingEvent <span style="color: #000000;">}</span><span style="color: #008000;">;</span>
method.<span style="color: #0000FF;">Invoke</span><span style="color: #000000;">(</span>handler, param<span style="color: #000000;">)</span><span style="color: #008000;">;</span> <span style="color: #008080; font-style: italic;">// .NET is nice enough to upcast ImProfilinfEvent coming back from object</span>
<span style="color: #000000;">}</span>
<span style="color: #000000;">}</span>
<span style="color: #000000;">}</span>
<span style="color: #0600FF;">private</span> <span style="color: #0600FF;">static</span> Type FindProfileEventinterface<span style="color: #000000;">(</span>ImProfilingEvent profilingEvent, IEnumerable<span style="color: #008000;"><</span>Type<span style="color: #008000;">></span> handlerInterfaces<span style="color: #000000;">)</span>
<span style="color: #000000;">{</span>
var profilerEventInterfaces <span style="color: #008000;">=</span> <span style="color: #008080; font-style: italic;">/* find the profiling event*/</span>
profilingEvent.<span style="color: #0000FF;">GetType</span><span style="color: #000000;">(</span><span style="color: #000000;">)</span>.<span style="color: #0000FF;">GetInterfaces</span><span style="color: #000000;">(</span><span style="color: #000000;">)</span>.<span style="color: #0000FF;">Where</span><span style="color: #000000;">(</span>
i <span style="color: #008000;">=></span> i <span style="color: #008000;">!=</span> <span style="color: #008000;">typeof</span><span style="color: #000000;">(</span>ImProfilingEvent<span style="color: #000000;">)</span> <span style="color: #008000;">&&</span> handlerInterfaces.<span style="color: #0000FF;">Any</span><span style="color: #000000;">(</span>h <span style="color: #008000;">=></span> h.<span style="color: #0000FF;">GetGenericArguments</span><span style="color: #000000;">(</span><span style="color: #000000;">)</span>.<span style="color: #0000FF;">First</span><span style="color: #000000;">(</span><span style="color: #000000;">)</span> <span style="color: #008000;">==</span> i<span style="color: #000000;">)</span><span style="color: #000000;">)</span><span style="color: #008000;">;</span>
<span style="color: #0600FF;">if</span> <span style="color: #000000;">(</span>profilerEventInterfaces.<span style="color: #0000FF;">Count</span><span style="color: #000000;">(</span><span style="color: #000000;">)</span> <span style="color: #008000;">></span> <span style="color: #FF0000;">1</span><span style="color: #000000;">)</span> <span style="color: #0600FF;">throw</span> <span style="color: #008000;">new</span> ArgumentException<span style="color: #000000;">(</span><span style="color: #666666;">"Multi-events not supported"</span><span style="color: #000000;">)</span><span style="color: #008000;">;</span>
<span style="color: #0600FF;">if</span> <span style="color: #000000;">(</span>profilerEventInterfaces.<span style="color: #0000FF;">Count</span><span style="color: #000000;">(</span><span style="color: #000000;">)</span> <span style="color: #008000;">==</span> <span style="color: #FF0000;">0</span><span style="color: #000000;">)</span> <span style="color: #0600FF;">throw</span> <span style="color: #008000;">new</span> ArgumentException<span style="color: #000000;">(</span><span style="color: #666666;">"invalid profilerEvent"</span><span style="color: #000000;">)</span><span style="color: #008000;">;</span>
<span style="color: #0600FF;">return</span> profilerEventInterfaces.<span style="color: #0000FF;">First</span><span style="color: #000000;">(</span><span style="color: #000000;">)</span><span style="color: #008000;">;</span>
<span style="color: #000000;">}</span>
<span style="color: #000000;">}</span> |
While this particular example uses some funky reflection to do auto-wiring (I know there are other ways to do that, but that’s how I am :) ) you can write simpler mixins that define some stuff in the interface and then go about using that and building some logic on it in the extension methods you provide with it. Not a perfect solution but useful non-the-less

