How to use Mixins in .NET

By Stefan Papp

Mixins are a powerful concept in object-oriented design. Unfortunately mixins are not included in the .NET Framework. re-mix is a library that brings mixins to .NET. The project is hosted at codeplex under http://remix.codeplex.com.

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)); }
}

How to use Mixins in .NET  (1154 Views)