Channels ▼

Arnon Rotem-Gal-Oz

Dr. Dobb's Bloggers

Mixins in .NET

December 15, 2010

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

Related Reading


More Insights






Currently we allow the following HTML tags in comments:

Single tags

These tags can be used alone and don't need an ending tag.

<br> Defines a single line break

<hr> Defines a horizontal line

Matching tags

These require an ending tag - e.g. <i>italic text</i>

<a> Defines an anchor

<b> Defines bold text

<big> Defines big text

<blockquote> Defines a long quotation

<caption> Defines a table caption

<cite> Defines a citation

<code> Defines computer code text

<em> Defines emphasized text

<fieldset> Defines a border around elements in a form

<h1> This is heading 1

<h2> This is heading 2

<h3> This is heading 3

<h4> This is heading 4

<h5> This is heading 5

<h6> This is heading 6

<i> Defines italic text

<p> Defines a paragraph

<pre> Defines preformatted text

<q> Defines a short quotation

<samp> Defines sample computer code text

<small> Defines small text

<span> Defines a section in a document

<s> Defines strikethrough text

<strike> Defines strikethrough text

<strong> Defines strong text

<sub> Defines subscripted text

<sup> Defines superscripted text

<u> Defines underlined text

Dr. Dobb's encourages readers to engage in spirited, healthy debate, including taking us to task. However, Dr. Dobb's moderates all comments posted to our site, and reserves the right to modify or remove any content that it determines to be derogatory, offensive, inflammatory, vulgar, irrelevant/off-topic, racist or obvious marketing or spam. Dr. Dobb's further reserves the right to disable the profile of any commenter participating in said activities.

 
Disqus Tips To upload an avatar photo, first complete your Disqus profile. | View the list of supported HTML tags you can use to style comments. | Please read our commenting policy.
 


Video