Click here to Skip to main content
15,890,506 members
Articles / Programming Languages / C#
Article

Mixin in C# 3

Rate me:
Please Sign up or sign in to vote.
3.34/5 (13 votes)
19 Sep 2005CPOL3 min read 43.2K   13   1
How to add mixin to a class in C# 3

Introduction

Note: It's probably pretty early to start talking about patterns for C# 3, but the thought popped in 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.

The Code

Let's see what we would like to write:

C#
//Creating 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:

C#
//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 extension methods that refer to the Taggable.Mixin<T> interface. The Taggable.Mixin<T> interface requires that the 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 extension method to add tags to an object, and a static method (not an extension one), which takes a Taggable.Mixin type and returns a list of the tagged instances of it. Check out the bolded lines, those are 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 has to do is to declare its intention to accept the mixin.

As I said, it's pretty premature 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 give you. I expect a lot more goodies along the way. The new features are useful for so much more beyond LINQ.

One thing to be 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.

For mixin today you can use Castle.DynamicProxy.

History

  • 19th September, 2005: Initial post

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
Israel Israel
This member has not yet provided a Biography. Assume it's interesting and varied, and probably something to do with programming.

Comments and Discussions

 
GeneralA nice practical use of Extention Methods Pin
egozi134-Aug-06 8:04
egozi134-Aug-06 8:04 
As someone with interest in Software Engeneering I'm into the possibilities in C#3.0, and It's nice to see practicle uses for the concepts introduced in this language.

Got my 5.

But I still have a point out a possible typo (or misunderstanding on my side) in the code:

the interface decleration:

public interface Mixin<t>
where T : ActiveRecordBase, Mixin<t> { }

should have been:

public interface ITaggable<t>
where T : ActiveRecordBase, Mixin<t> { }

as stated in the extention method: "public static void TagWith(this ITaggable<t> ... )"


Whatever language you use, just write in a clear and readable manner, or else It wouldn't be a language at all ...
http://www.kenegozi.com/blog

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.