[pMixins]

A lightweight open source Mixin and AOP framework for C#


Non Public & Non Parameterless Constructor

[pMixins] will automatically try and create instances of Mixins for you by using the MixinActivatorFactory. However, this class cannot create an instance of a Mixin if it does not have a parameterless constructor (the constructor can be protected though!)

If you want to mixin a Mixin with a non-parameterless constructor (and you aren't using Dependency Injection) or if you want to use a specific constructor, you'll need to create instances of Mixins in your Target class. You can tell [pMixins] you want to do this by setting the ExplicitlyInitializeMixin flag to true.

This flag causes [pMixins] to add a special interface, IMixinConstructorRequirement to your Target. This interfaces has a method, InitializeMixin where you can create instances of Mixins using whichever constructor you want.

There are two special caveats to this. First, if the Mixin is abstract, C# will not let you create an instance of an abstract class. Second, if you want to call a protected constructor, C# will not let you. For both cases you can create an instance of the abstract wrapper [pMixins] creates for you (see How it Works for more information on the abstract wrapper). This class will always be concrete and all protected constructors will be promoted to public.

So let's define a two Mixins we can use to demonstrate this. First is Mixin which has a public parameterless constructor and a protected constructor that takes an int.

public class Mixin
{
   public Mixin()
   {
      FavoriteNumber = 42;
   }
   protected Mixin(int favoriteNumber)
   {
      FavoriteNumber = favoriteNumber;
   }
   public int FavoriteNumber {
      get;
      private set;
   }
}

Second is AbstractMixin, which only has a protected non-parameterless constructor:

public abstract class AbstractMixin
{
   protected AbstractMixin(int favoriteNumber)
   {
      AbstractFavoriteNumber = favoriteNumber;
   }
   public int AbstractFavoriteNumber {
      get;
      private set;
   }
}

So let's see how we can mixin Mixin and AbstractMixin into a Target:

[pMixin(Mixin = typeof(Mixin), ExplicitlyInitializeMixin = true)]
[pMixin(Mixin = typeof(AbstractMixin), ExplicitlyInitializeMixin = true)]
public partial class NonPublicNonParameterlessConstructor
{
   Mixin IMixinConstructorRequirement<Mixin>.InitializeMixin()
   {
      return new MixinAbstractWrapper(this, 1);
   }
   AbstractMixin IMixinConstructorRequirement<AbstractMixin>.InitializeMixin()
   {
      return new AbstractMixinAbstractWrapper(this, 1);
   }
}

The first thing to notice in NonPublicNonParameterlessConstructor is both pMixin attributes set the ExplicitlyInitializeMixin flag to true. The InitializeMixin is then implemented for both Mixins. In this case they are implemented explicitly. This is best practice, as there is no reason for Target to expose this method publically.

Looking deeper into the InitializeMixin methods, the first thing to notice is the method for Mixin has to work a lot harder to get to the MixinAbstractWrapper as it is buried in the [pMixins]'s Auto Generated infrastructure. There is currently an improvement issue registered on GitHub to fix this. Also, it is important to notice the use of this in the parameter list for the abstract wrappers constructor. These wrappers require an instance of the Target be passed in.

Finally, NonPublicNonParameterlessConstructorTest proves that we can call both FavoriteNumber and AbstractFavoriteNumber from the Target NonPublicNonParameterlessConstructor:

[TestFixture]
public class NonPublicNonParameterlessConstructorTest
{
   [Test]
   public void NonAbstractMixin()
   {
      Assert.AreEqual(1, new NonPublicNonParameterlessConstructor().FavoriteNumber);
   }
   [Test]
   public void AbstractMixin()
   {
      Assert.AreEqual(1, new NonPublicNonParameterlessConstructor().AbstractFavoriteNumber);
   }
}

Download the source for this and all other recipes Here!