re-mix - A Mixin Library for .NET
Introduction
Mixins are a powerful concept to improve OOP structures. Unfortunately, mixins are not part of the .NET Framework.
In the article Mixin in C# 3, the author Ayende Rahien presented his ideas to implement mixins with C# 3.0. His use case “adding tags to objects” is a perfect reference sample for mixins.
In this article, we rewrite this sample, because Ayende Rahien's article was just about a concept, he did not implement the sample.
We will also use a different technology. Extension Methods are syntactic sugar for static methods and they lack two important functionalities required for mixins: they cannot store states to objects and they cannot be part of an interface. Ayende Rahien referred to using Castle.DynamicProxy as a possible solution to that problem.
In this article, we will use the re-mix library to implement the sample. re-mix is a library specially designed to bring mixins to .NET. It provides a rich set of additional functionality for mixins. re-mix can be downloaded from its CodePlex page.
Using the Code
Let’s jump right into the code:
public interface ITaggable
{
void TagWith(string[] tags);
string AllTags ();
}
public class TaggableMixin : ITaggable
{
private readonly List<string> _tags = new List<string>();
public void TagWith(string[] tags)
{
_tags.AddRange (tags);
}
public string AllTags()
{
return _tags.Aggregate(string.Empty, (current, s) => current + “ “ + s);
}
}
This code shall be mixed into a target class. As you can see, this is pure standard C# code.
We will now see how the class TaggableMixin
can be “turned into a mixin”. Let’s have a look at a reference implementation that uses TaggableMixin
:
[Uses (typeof (TaggableMixin))]
public class Photo
{
public string Name { get; set; }
}
var vacationPhoto = ObjectFactory.Create<Photo>();
vacationPhoto.Name = "HolidayPic1";
ITaggable t = ((ITaggable) vacationPhoto);
t.TagWith(new[] {"Holiday", "Private", "Sunset"});
Console.WriteLine("Photo {0} is tagged with {1}",
vacationPhoto.Name, t.AllTags());
This is the first time in the source code that we are using the re-mix library. The “target class” (i.e., the class that should be extended with the mixin’s functionality) gets annotated by a Uses
attribute which is provided by re-mix. This code tells the mixin engine that the target class uses TaggableMixin
.
We also have to tell the mixin engine that we want to instantiate a “mixed object” of Photo
and its mixins. For this we have to call the ObjectFactory.Create
method. If we use the standard constructor, we would create a POCO (plain old CLR object) photo object without any mixins.
Once the mixed object is instantiated, the last remaining issue is to access the mixin. For this, we have to cast the mixed object to its mixin interface. Then we are able to access every functionality provided by the mixin.
Points of Interest
This article is an appetizer for more. Among other things the following is possible with re-mix:
- You can configure mixins declaratively by configuration:
- A class uses a mixin
- A mixin extends a class or class tree
- An assembly connects classes with mixins
- Add/remove mixins dynamically to/from the class
- Use patterns to access mixin functionality without casts
- Override methods of the target class in a mixin
- Override mixin methods in the target class
It is out of the scope to explain these features in an introductory article. I recommend downloading the library from the CodePlex page. Try out some examples from the hands on lab! If you get stuck or run into problems, don't hesitate to ask the developers on the mailing list at this Google page.