advanced re-motion mixins -- dessert wax revisited

Let's say we want to build our own configuration from scratch for mixing a floor wax to a dessert topping, as demonstrated in the first exercise of this tutorial – re-motion mixins basics -- the 'Uses' attribute and the 'ObjectFactory'. To this end, we create an empty mixin configuration builder with

MixinConfiguration.BuildNew ()

MixinConfiguration is our gateway to the re-motion mixin library; BuildNew is a static method that gives you an emtpy builder object. This is not the mixin configuration, it is an intermediate represenation for convenient building. After getting our empty mixin configuration builder, we can add items to it by gluing commands together like this:

MixinConfiguration.BuildNew () // set up new builder
.ForClass<TargetClass1> ().AddMixin<MixinClass1> ().AddMixin<MixinClass2> ().AddMixinClass<MixinClass3> ()         // mix mixin 1, 2 and 3 to target class 1
.ForClass<TargetClass2> ().AddMixin<MixinClass4> ().AddMixin<MixinClass5> ()                                       // mix mixin 4 and 5 to target class 2
...
.BuildConfiguration (); // make actual configuration from builder

This manner of piling stuff on an instance is a well-established pattern called the fluent interface pattern. Note the last command in the chain, the concluding .BuildConfiguration. This method creates the actual mixin configuration from the builder representation. The builder is required to make the convenient mechanics of the fluent interface pattern work.

For our dessert wax example, this means:

var myMixinConfiguration = MixinConfiguration.BuildNew () // make builder
.ForClass<DessertTopping> ().AddMixin<FloorWax> ()        // add items to the builder by chaining methods (= fluent interface)
.BuildConfiguration ();                                   // run builder to make mixin configuration

Since we build the mixin configuration ourselves, there is no need to attribute any of the involved classes. What we DO have to do is to set the freshly constructed mixin configuration active for the current thread:

MixinConfiguration.SetActiveConfiguration (myMixinConfiguration); // only affects this thread

From that point on, our nameless mixed class can be exercised as in the examples on previous pages of this tutorial. Here is a complete listing.

  // Note that we don't use a [Uses] attribute.
  // We don't need any attributes here, because all
  // configuration work is done via the fluent interface
  // (see listing below).
  public class DessertTopping
  {
    public void TasteGood ()
    {
      Console.WriteLine ("Mmmmmm, tastes terrific!");
    }
  }

  public interface IFloorWaxMixin
  {
    void SealFloor ();
  }

  // Note that we don't use an [Extends] attribute.
  // The method chaining (fluent interface, see below)
  // does all the configuration work.
  public class FloorWaxMixin : IFloorWaxMixin
  {
    public void SealFloor ()
    {
      Console.WriteLine ("Dirt, grime, even black heel marks -- wipe clean with a damp mop!");
    }
  }


  class Program
  {
    static void Main (string[] args)
    {
      // you must force the .NET runtime to load a reference to the
      // Remotion.dll assembly. Otherwise the compiler will remove the
      // facilities for loading the Remotion.dll assembly and your application
      // will throw a type initializer exception, because it can't load it.
      // The easiest way to touch the assembly is to use the IMixinTarget
      // identifier:
      FrameworkVersion.RetrieveFromType (typeof (IMixinTarget));

      // instantiate and build a new mixin configuration.
      // In the previous samples, we've done that by using
      // attributes.
      var myMixinConfiguration = MixinConfiguration.BuildNew ()
          .ForClass<DessertTopping> ().AddMixin<FloorWaxMixin> ()   // mix 'FloorWaxMixin' to 'DessertTopping'
          .BuildConfiguration ();

      // make that mixin configuration active for this thread
      MixinConfiguration.SetActiveConfiguration (myMixinConfiguration);

      // this is same old same old... instantiate mixed class
      var myDessertWax = ObjectFactory.Create<DessertTopping> (ParamList.Empty);
      myDessertWax.TasteGood ();
      ((IFloorWaxMixin) myDessertWax).SealFloor ();

      Console.ReadLine ();
    }
  }
Sample code

You find the sample code for this exercise in subversion.