re-motion mixins basics -- what about sub-classes of the target class?

Classes derived from the target class "inherit" all mixins from the target class. In section re-motion mixins basics -- the generic 'Mixin' type we will make extensive use of a Parrot class. Many types of parrots exist – the clever grey parrot, the colorful macaw, the red (marxistic-leninistic?) Cuban parrot. The list in wikipedia goes on and on. Assuming we have a parrot hierarchy with Parrot as base class, we can mix in a CircusMixin to teach parrots how to ride the unicycle:

  public class Parrot
  {
    public virtual void Fly ()
    {
      Console.WriteLine ("Flapflap...");
    }

    public virtual void Whistle ()
    {
      Console.WriteLine ("<river kwai march here>");
    }

    public virtual void Say (string s)
    {
      Console.WriteLine ("\"{0}\"", s);
    }
  }

  public class GreyParrot : Parrot
  {
    public virtual void DestroyFurniture ()
    {
      Console.WriteLine ("Destroying furniture...");
    }
  }

  public class Macaw : Parrot
  {
    public virtual void CrackNut ()
    {
      Console.WriteLine ("Cracking nut...");
    }
  }

  public interface ICircusMixin
  {
    void RideUniCycle ();
  }

  [Extends (typeof (Parrot))]
  public class CircusMixin : ICircusMixin
  {
    public void RideUniCycle ()
    {
      Console.WriteLine ("I'm so amazing! I'm riding a unicycle!");
    }
  }

Mixing the CircusMixin to parrot will mix it to the sub-classes GreyParrot and Macaw automatically. Not only the Parrot, also the GreyParrot and the Macaw acquire unicycle-skills:

      // Don't forget to touch the API in the library
      FrameworkVersion.RetrieveFromType (typeof (IMixinTarget));

      var myCircusParrot = ObjectFactory.Create<Parrot> (ParamList.Empty);
      Console.WriteLine ("Parrot:");
      myCircusParrot.Whistle ();                        // do as parrots do
      ((ICircusMixin) myCircusParrot).RideUniCycle ();  // show off what you have learned
      Console.WriteLine ();

      Console.WriteLine ("GreyParrot:");
      var myCircusGreyParrot = ObjectFactory.Create<GreyParrot> (ParamList.Empty);
      myCircusGreyParrot.DestroyFurniture ();               // grey parrots LOVE destruction
      ((ICircusMixin) myCircusGreyParrot).RideUniCycle ();  // show off what you have learned from your ancestor
      Console.WriteLine ();

      Console.WriteLine ("Macaw:");
      var myCircusMacaw = ObjectFactory.Create<Macaw> (ParamList.Empty);
      myCircusMacaw.CrackNut ();                            // for a macaw, a nut is like a zip-loc; keep hands and feet clear!
      ((ICircusMixin) myCircusMacaw).RideUniCycle ();       // show off what you have learned from your ancestor
      Console.WriteLine ();

We have used the Extends attribute for mixing here. Again, it does not matter whether you attribute the mixin class with Extends or the target class with Uses – mixing is inheritable up the class hierarchy.

Sample code

The sample code for this example is in https://svn.re-motion.org/svn/Remotion-Contrib/Samples/Mixin/WikiSamples/trunk/WikiSamples.ParrotSubclasses/Program.cs

See also

You can exclude arbitrary subclasses from being mixed. This is an advanced topic and discussed in section advanced re-motion mixins -- removing items, scoping of mixin configurations.