re-motion mixins basics -- the 'Extends' attribute

In practice, you probably won't use the Uses attribute very often. Mixins are a good way to extend framework classes (re-motion classes, for example). This works best when the framework classes don't even know that they are extended, when no modification of their source code is necessary. This is in contrast to the first example, where DessertTopping is extended by telling it to mix in the FloorWax mixin class.

A much more practical route for extending target classes is the Extends attribute. Instead of telling the target class to use a mixin, you tell the mixin class that it extends one or more target classes:

[Extends (typeof (DessertTopping))]
public class FloorWaxMixin : IFloorWaxMixin
{
  public void SealFloor ()
  {
    Console.WriteLine ("Dirt, grime, even black heel marks -- wipe clean with a damp mop!");
  }
}

The framework code, where the extended DessertTopping resides, remains unaffected. This is of particular utility if you don't have the source code for the framework. Cluttering framework code with application-specific code is frowned upon by programmers, and rightly so. Therefore, the Extends attribute is preferable for most cases, even if you DO have the source code for the extended class. Attributing the target class with Uses CAN be
beneficial, but such cases are fairly rare. Expect to use Extends much more often.

A mixin can extend multiple target classes, for example

[Extends (typeof (DessertTopping))]
[Extends (typeof (IceCream))]
[Extends (typeof (Pudding))]
public class FloorWaxMixin : IFloorWaxMixin
{
  public void SealFloor ()
  {
    Console.WriteLine ("Dirt, grime, even black heel marks -- wipe clean with a damp mop!");
  }
}
Uses and Extends are mutually exclusive for the same mixing

Using instances of mixed classes is not influenced by how you mix them, i.e. the code works without regard to who extends whom. Whether you put a Uses attribute on the target class or the Extends attribute on the mixin class does not matter. However, never use BOTH for the same mixing. This is redundant, so re-motion mixins will believe you are confused and made a mistake and throw an exception to bring the mistake to your attention:

// *** THIS IS WRONG SAMPLE CODE ***

[Uses (typeof (FloorWaxMixin))]
public class DessertWax
{
  public void TasteGood ()
  {
    Console.WriteLine ("Mmmmmm, tastes terrific!");
  }
}

// *** Either use 'Uses' or 'Extends'; using BOTH is a mistake
[Extends (typeof (DessertTopping))]
public class FloorWaxMixin : IFloorWaxMixin
{
  public void SealFloor ()
  {
    Console.WriteLine ("Dirt, grime, even black heel marks -- wipe clean with a damp mop!");
  }
}

The bogus code above will compile and link, but it will result in an exception at run-time, when ObjectFactory tries to mix and instantiate your broken configuration:

Two instances of mixin DessertWax.Uses.FloorWaxMixin are configured for target type DessertWax.Uses.DessertTopping.

Likewise, it is prohibited to put two or more Uses or Extends attributes with the same arguments on the same class.

Sneak preview on re-motion mixins and duck typing

What makes mixins useful is that you can apply them to an arbitrary number of classes, but this flexibility usually goes out the window if your mixin assumes certain members for overriding. However, as we will see later (in re-motion mixins basics -- duck typing), these classes need not to be related in any way. For example, you could have a totally unrelated Hamburger class with a method that coincidentally has the name TasteGood, as found in DessertTopping.

Hamburger does not need to share anything with the DessertTopping class, not even an interface. Since re-motion mixins mixes via .NET reflection features, the mixing will work anyway. This duck typing is a hallmark of more dynamic languages like python or ruby, but re-motion mixins make it easy to use in .NET, too.

Sample Code

You find the sample code for this wiki page in subversion