Mixin & Dicing in C# 3

time to read 8 min | 1568 words

Note: It's probably pretty early to start talking about patterns for C# 3, but the thought popped to my mind and wouldn't go away.

Mixin: In computer science, a mixin is a group of functions which can be mixed into a class and become methods. They allow certain classes to take on certain functionality, in an object-oriented programming including in languages that do not support multiple inheritance, just as if the class were a cooking dish and a mixin was a specific ingredient.

Ruby on Rails recently got a act_as_taggable mixin, which basically allows you to just slap a single line of code on a class and get tagging support. I'm going to show the C# 3 interface for a similar implementation. I don't care about the implementation, so we'll just assume that this is a given. I want to be able to tag any database object with as few lines of code as possible and just have it work like magic, the ideal is Ruby's single line of code. I'm going to show the ideal, the interface & client code and then talk about how this is possible.

Let's see what we would like to write:

//Createing taggable mixin
public mixin Taggable<T>
{
 public void TagWith(params string tags) { .. }

 public static T TaggedWith(params string tags, FindWith with) { .. }
}
public enum FindWith 
{
 AnyOfTheTags,
 AllTheTags
}
//Adding tagging to a class


public class Photo : Taggable
{
...
}

//client code:
// create photo and adding tags
Photo photo = ... ;
photo = Photo.TaggedWith("flower","sun","yellow""mayhem");
//Loading with tags

Photo photo = Photo.TaggedWith("flower", FindWith.AnyOfTheTags);

This is what we would like to have, but right now and in the future we are not likely to get it. We can get something very close. Here is what we would need to write:

//creating taggable mixin


namespace Tagging
{
 public static class Taggable
 {
  public static void TagWith(this ITaggable<T> tagged, params string tags) { .. }

  public static IList<T> TaggedWith<T>(params string tags, FindWith with) where T : ITaggable<T> { .. }

 public interface Mixin<T> 
  where T : ActiveRecordBase, Mixin<T>   { }
 }
 
 public enum FindWith 
 {
  AnyOfTheTags,
  AllTheTags
 } 
}
//Adding tagging to a class
public class Photo : ActiveRecordBase, Taggable.Mixin<Photo>
{
...
}
//client code

using Tagging;
//create photo and adding tags
Photo photo = ... ;
photo.TagWith("sun","rain","colors");
//load photo with tags
IList<Photo> photoWithFlowers = Taggable.TaggedWith<Photo>("chaos",  FindWith.AnyOfTheTags);

So, what do we have here? We have a static class with extention methods that refer to the Taggable.Mixin<T> interface. The Taggable.Mixin<T> interface require that implementing class will inherit from ActiveRecordBase and implement ITaggable*, this is so the Taggable class will have a way to work with the database, (that is an implementation detail, it can certainly be done in other ways).

Then we have the Taggable class, which has an extention method to add tags to an object, and a static method (not an extention one), which takes a Taggable.Mixin type and return a list of the tagged instances of it. Check out the bolded lines, those is what you've to do in order to get the taggable support for an object. Add a declaration to Taggable.Mixin, and your object is set. Then in the client code just import the Tagging namespace, and you can use it as if it was part of the object.

I think that this is a really nice way to add functionality to objects in a non intrusive way. The client code can actually choose whatever it wants to be exposed to the tagging support or not, and all the class have to do is to declare its intention to accept the mixin.

As I said, it's a pretty pre-mature to start thinking about patterns for C# 3 (C# 2 is not yet released, after all), but I'm willing to bet quite a sum that this will be the way to create mixins is the .Net framework. This is just one of the cool things that you can do with the things that C# 3 will gives you. I expect a lot more goodies along the ways. The new features are useful for so much more beyond Linq.

One thing to considered, it's pretty early to say anything, but I can certainly see libraries such as the Boost providing tremendous value for developers in the C# 3 world.

* Implementing Taggable.Mixin - since Taggable.Mixin is an empty interface, the constraints here are just a way to say that any Taggable.Mixin must inherit from ActiveRecordBase. It's a nice way to declare things, since now we can say: ITaggable<Photo> is ActiveRecordBase, and it's always true.