Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.
Wiki Markup
{remotion-mixins-disclaimer} 



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 
{code}
MixinConfiguration.BuildNew ()
{code}

{{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: 

{code}
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
{code}

This manner of piling stuff on an instance is a well-established pattern
called the [_fluent interface pattern_ ([|http://en.wikipedia.org/wiki/Fluent_interface]).
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:

{code}
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
{code}

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:

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

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. 

{code}
  // 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 ();
    }
  }
{code}  

h5. Sample code

You find the sample code for this exercise at
[https://svn.re-motion.org/svn/Remotion-Contrib/Samples/Mixin/WikiSamples/trunk/WikiSamples.DessertWaxFluentInterface/Program.cs]