They are supported by many common languages, such as Ruby and C++. There are many blogs about the possibility to use extension methods to emulate mixins.
But extension methods are stateless. They are no substitute for mixins.
re-mix is a library that brings mixins to .NET. This project is hosted at codeplex
under http://remix.codeplex.com.
The following code illustrates the basic usage of re-mix in one simple use case.
EquatableByValuesMixin is a mixin to determine if two objects are equal. The
main idea is to implement the mixin in a class. The mixin can be later mixed
to the "target class" by adding class attributes. The rest is done
by the mixin engine of re-mix.
This is just a basic sample for the usage of mixins. For more details and further
samples go to http://remix.codeplex.com!
using System;
using System.Linq;
using System.Reflection;
using Remotion.Mixins;
namespace EqualsShowCase.MixinImplementation
{
public class EquatableByValuesMixin<T> : Mixin<T>, IEquatable<T> where T : class
{
private static readonly FieldInfo[] s_targetFields = typeof (T).GetFields (
BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
bool IEquatable<T>.Equals (T other)
{
if (other == null)
return false;
if (Target.GetType () != other.GetType ())
return false;
for (int i = 0; i < s_targetFields.Length; i++)
{
object thisFieldValue = s_targetFields[i].GetValue (Target);
object otherFieldValue = s_targetFields[i].GetValue (other);
if (!Equals (thisFieldValue, otherFieldValue))
return false;
}
return true;
}
[OverrideTarget]
public new bool Equals (object other)
{
return ((IEquatable<T>)this).Equals (other as T);
}
[OverrideTarget]
public new int GetHashCode ()
{
int i = 0;
foreach (FieldInfo f in s_targetFields)
i ^= f.GetValue (Target).GetHashCode ();
return i;
}
}
[Uses (typeof (EquatableByValuesMixin<Address>))]
public class Address
{
public string City;
public string ZipCode;
public string Country;
}
public class StreetAddress : Address
{
public string Street; public string StreetNumber;
}
}
static void MixinImplementation ()
{
var wien = ObjectFactory.Create<EqualsShowCase.MixinImplementation.StreetAddress> (ParamList.Empty);
var berlin = ObjectFactory.Create<EqualsShowCase.MixinImplementation.StreetAddress> (ParamList.Empty);
Console.WriteLine ("Mixed Implementation StreetAddress: Both instances have the same values: {0}", Equals (wien, berlin)); }
}