Emulating MixIns with C#

One of the shortcomings of C# is the missing support of MixIns, which are a popular substitute for multiple inheritance especially in Ruby. MixIns provide a way to put a common functionality in a separate classand use it in another class. That is still easy in C#, one can simply use inheritance. But, what will you do, when your classes are already inheriting from other classes? You won't want to break up your inheritance hierarchie for this, will you? Using a MixIn, you can put a common functionality in a separate class and mix it into multiple classes, regardless of their inheritance hierarchy. The methods and properties of a MixIn-class are merged into the using classes' interface and can also use the original classes members. That's the theory and what is possible in Ruby, but can it be achieved in C#? If you need an example for MixIns, you might want to read the following blog post http://www.juixe.com/techknow/index.php/2006/06/15/mixins-in-ruby/. However, you don't need any Ruby knowledge for the remainder of my post. Ok, what are the characteristics of a MixIn again:
  1. Accessible via the using class
  2. Has access to the using class' instance members
  3. Must not use inheritance

Taking into account that C# is a statically and strongly typed compiled language, this is not possible at first glance. But, if all possibilities of C# are used, they can be fulfilled at least partially.

As an example, I will develop a MixIn that adds reduction-functionality to collections. Reduction is a functional programming concept means that the collection will be reduced (boiled down) to a scalar value using a user-specified delegate. Simple reductions are joining a collection of strings or adding up a collection of integers.

The following code shows how this can be implemented using a conventional static method:

    1 using System.Collections.Generic;
    3 namespace Example
    4 {
    5     public delegate TItem ReduceDelegate<TItem>(
    6         TItem firstItem, 
    7         TItem secondItem);
    9     public static class Reduction
   10     {
   11         public static TItem Reduce<TItem>(
   12             IEnumerable<TItem> collection, 
   13             ReduceDelegate<TItem> reduceFunction)
   14         {
   15             TItem result = default(TItem);
   16             bool first = true;
   17             foreach (TItem item in collection)
   18             {
   19                 if (first)
   20                 {
   21                     result = item;
   22                     first = false;
   23                 }
   24                 else
   25                 {
   26                     result = reduceFunction(result, item);
   27                 }
   28             }
   29             return result;
   30         }
   31     }
   32 }
Now the question is, how can this functionality be implemented as a mixin. We will need at least to interfaces for this:
  • An interface that allows the mixin access to the using class.
  • An external interface that allows a client to use the functionality provided by the mixins.

The code below shows how these are declared:

    1 namespace Mixin
    2 {
    3     public delegate TItem ReduceDelegate<TItem>(
    4         TItem firstItem, 
    5         TItem secondItem);
    7     public interface IReduceClient<TItem> : IEnumerable<TItem>{}
    9     public interface IReduceMixin<TItem>
   10     {
   11         TItem Reduce(ReduceDelegate<TItem> reduceFunction);
   12     }
   14     public interface IWithReduce<TItem> : IReduceClient<TItem>, IReduceMixin<TItem> {}
   16     public class ReduceMixin<TItem> : IReduceMixin<TItem>
   17     {
   18         public ReduceMixin(IReduceClient<TItem> client)
   19         {
   20             this.client = client;
   21         }
   23         private readonly IReduceClient<TItem> client;
   25         public TItem Reduce(ReduceDelegate<TItem> reduceFunction)
   26         {
   27             TItem result = default(TItem);
   28             bool first = true;
   29             foreach (TItem item in client)
   30             {
   31                 if (first)
   32                 {
   33                     result = item;
   34                     first = false;
   35                 }
   36                 else
   37                 {
   38                     result = reduceFunction(result, item);
   39                 }
   40             }
   41             return result;
   42         }
   43     }
   44 }

Line 7 declares the interface that the mixin uses to access the using class (IReduceClient). This can be arbitrary complex, but in this case, we only need an enumeration, so I just inherited from IEnumerable. Line 9 declares the interface that is publicly used to access the mixin's functionality (IReduceMixin). IWithReduce on line 14 just brackets the other two interfaces, so that an using class can specify IWithReduce, which shows the intention better than using the two different interfaces.

The mixin class is shown on lines 16ff. It simply holds a reference to the client, a.k.a. the using class and the Reduce implementation shown above.

Now the problem is how can the mixin added to a client. The code below would be ideal, but won't work with C# 2.0:

    1 namespace Client
    2 {
    3     public class ReducableList<T> : List<T>, IWithReduce<T>
    4     {
    5         // Won't work that way!
    6     }
    7 }

Before I show a (naive) implementation, here is the test code for the whole thing, that shows how it is used:

    1 namespace Test
    2 {
    3     [TestFixture]
    4     public class ReduceTest
    5     {
    6         [Test]
    7         public void TestMixin()
    8         {
    9             ReducableList<string> rl = new ReducableList<string>();
   10             rl.AddRange(new string[] {"a", "b", "c"});
   12             IReduceMixin<string> reducable = rl;
   13             Assert.AreEqual("a,b,c", reducable.Reduce(delegate(string s1, string s2) { return s1 + "," + s2; }));
   15             ReducableList<int> rli = new ReducableList<int>();
   16             rli.AddRange(new int[] {1, 2, 3, 4});
   17             Assert.AreEqual(10, rli.Reduce(delegate(int i, int j) { return i + j; }));
   18         }
   19     }
   20 }

R# Jedi

One simple, naive and somewhat cheating method to make the ReducableList work, is using ReSharper. Just add a IRecudeMixin field and choose Alt+Ins/Delegate members. As a finishing touch you need to initialize the field.

The resulting code is shown below:

    1 namespace Client
    2 {
    3     public class ReducableList<T> : List<T>, IWithReduce<T>
    4     {
    5         public ReducableList()
    6         {
    7             reducer = new ReduceMixin<T>(this);
    8         }
   10         // Other constructors omitted for brevity
   12         private readonly ReduceMixin<T> reducer;
   14         public T Reduce(ReduceDelegate<T> reduceFunction)
   15         {
   16             return reducer.Reduce(reduceFunction);
   17         }
   18     }
   19 }

Well, I know that this is not a viable solution for maintainable software, but it is at least a quick fix and an introduction for the next article, which will show how to use DynamicProxy2 for creating a ReducableList without ReSharper Jedi.


The Component Burden Concept

Important Note: Mort that I am, I have mistaken ReleasePolicy for Component Burden and blogged about the former... As soon as I know what I am writing about, I will update that post.

There is a discussion on the Castle mailing list recently about the Component Burden problem. This is one of the oldest Castle issues (and the oldest that is not resolved by now). Now, the issue got a little bit of momentum by Ayende's post and Hammett's blog entry about it.

In short, the problem is this: If there are non-singleton components created by the IoC-Container that implement IDisposable, someone sometime needs to call Dispose(). However, both someone and sometime pose a problem:

  • Someone could be the using code or the container. It has been proposed that a component should dispose it's dependencies itself, but if you think about it, this is problematic because the component cannot know it's dependencies' lifestyles. Just imagine a service configured to run as a singleton being disposed after the very first request it served, because an using component doesn't need it anymore. Additionally there is a simple principle about resource allocation: The code that allocates a resource is responsible for deallocation too. Period. Back when C/C++ was used, every developer adhered to that principle because there was no GC...
  • Sometime is dependent on the components lifestyle. A singleton must not be disposed before the container shuts down itself while a transient component must be disposed as soon as possible to free allocated resources.

Now it is clear that the container is fully responsible for both construction and destruction of dependency objects. But how will it know, when the component is not used anymore?

Well, at least one component must be resolved from the container. This component must be released after you are finished using it:

MyComponent c = container.Resolve<MyComponent>(); // Some work container.Release(c);

Do you need to do this even if you're component is not disposable? Yes, because it can have direct or indirect dependencies that are disposable. If you don't release it, the container cannot know that it is now safe to dispose these dependencies, when they are otherwise unused.

Now there is one thing missing: The container must keep track of the dependencies. Assume that your component uses a custom per-web-request-logger that uses a FileStream.

Every time you resolve a component that uses the logger in one web request, the dependency will be fulfilled with the same logger. If you release a component, the container must remember that it used the logger, then check whether the logger is still used by other instances and if not, dispose the logger.

This bookkeeping of dependencies and disposal is called the component burden in the Castle project.

Although I don't know Microkernel's source code for this, I have an idea how to implement such a concept. But this is a topic for another post.