I've heard that it's possible with extension methods, but I can't quite figure it out myself. I'd like to see a specific example if possible.
Thanks!
I've heard that it's possible with extension methods, but I can't quite figure it out myself. I'd like to see a specific example if possible.
Thanks!
It really depends on what you mean by "mixin" - everyone seems to have a slightly different idea. The kind of mixin I'd like to see (but which isn't available in C#) is making implementation-through-composition simple:
public class Mixin : ISomeInterface
{
private SomeImplementation impl implements ISomeInterface;
public void OneMethod()
{
// Specialise just this method
}
}
The compiler would implement ISomeInterface just by proxying every member to "impl" unless there was another implementation in the class directly.
None of this is possible at the moment though :)
There is an open source framework that enables you to implement mixins via C#. Have a look on http://remix.codeplex.com/.
It is very easy to implement mixins with this framework. Just have a look on the samples and the "Additional Information" links given on the page.
LinFu and Castle's DynamicProxy implement mixins. COP (Composite Oriented Programming) could be considered as making a whole paradigm out of mixins. This post from Anders Noras has useful informations and links.
EDIT: This is all possible with C# 2.0, without extension methods
I've found a workaround here, which while not entirely elegant, allows you to achieve fully observable mixin behavior. Additionally, IntelliSense still works!
using System;
using System.Runtime.CompilerServices; //needed for ConditionalWeakTable
public interface MAgeProvider // use 'M' prefix to indicate mixin interface
{
// nothing needed in here, it's just a 'marker' interface
}
public static class AgeProvider // implements the mixin using extensions methods
{
static ConditionalWeakTable<MAgeProvider, Fields> table;
static AgeProvider()
{
table = new ConditionalWeakTable<MAgeProvider, Fields>();
}
private sealed class Fields // mixin's fields held in private nested class
{
internal DateTime BirthDate = DateTime.UtcNow;
}
public static int GetAge(this MAgeProvider map)
{
DateTime dtNow = DateTime.UtcNow;
DateTime dtBorn = table.GetOrCreateValue(map).BirthDate;
int age = ((dtNow.Year - dtBorn.Year) * 372
+ (dtNow.Month - dtBorn.Month) * 31
+ (dtNow.Day - dtBorn.Day)) / 372;
return age;
}
public static void SetBirthDate(this MAgeProvider map, DateTime birthDate)
{
table.GetOrCreateValue(map).BirthDate = birthDate;
}
}
public abstract class Animal
{
// contents unimportant
}
public class Human : Animal, MAgeProvider
{
public string Name;
public Human(string name)
{
Name = name;
}
// nothing needed in here to implement MAgeProvider
}
static class Test
{
static void Main()
{
Human h = new Human("Jim");
h.SetBirthDate(new DateTime(1980, 1, 1));
Console.WriteLine("Name {0}, Age = {1}", h.Name, h.GetAge());
Human h2 = new Human("Fred");
h2.SetBirthDate(new DateTime(1960, 6, 1));
Console.WriteLine("Name {0}, Age = {1}", h2.Name, h2.GetAge());
Console.ReadKey();
}
}
There are, fundamentally, several techniques to getting Mixin behavior in your classes:
IEnumerable and IDisposable) can use default interface members with explicit implementation of said interface. Then, then new interface behaves as a mixin where concrete behavior can be added and leveraged without using extension methods, and can support constructs such as using and foreach.ConditionalWeakTable to hold data.