This is the fourth in a series posts. The previous items are:
- It provides a mixin mechanism
- What’s a re-motion mixin, anyway?
- What can we do for you? (Features of re-motion mixins)
Last time, I briefly mentioned configuration as a feature of the re-motion mixin implementation. In the context of mixins, the term “configuration” refers to what mixins are mixed into what target classes, and with what properties the mixing is performed.
To be honest, the notion of configuration is more a prerequisite than a feature – without the ability of assigning mixins to target classes, a mixin implementation would be rather stupid. Or… not a mixin implementation at all, actually. What is a feature, however, is how many ways of configuration we allow.
I quickly repeat them from my last post:
- A class can declaratively choose to be extended by one or more mixins.
- A mixin can declaratively choose to extend one or more classes.
- An application can declaratively choose to combine mixins and classes.
- A programmer can – at run-time – choose to combine mixins and classes.
- (Any person can – at deployment time – choose to combine mixins and classes.)
–> planned, but not implemented yet
Today, I’ll write about the first three topics – the declarative configuration possibilities.
A class can choose its mixins
When you write a new class, you can explicitly pull in a number of mixins into that class. This feature is similar to inheritance (where you explicitly derive from a base class), and it enables scenario (1) from my post on usage scenarios: having a class reuse an implementation supplied by a mixin.
Let’s look at an example:
[Uses (typeof (MyMixin))]
public class MyClass
That’s quite self-explaining, I think – MyClass has chosen to use (ie. include) the reusable code provided by MyMixin.
Now, what would you use that for, and what additional properties can you specify?
You would choose this form of configuration when you have a mixin providing a feature that you want your class to expose. The mixin’s implementation actually becomes part of the class’s implementation. Think of deriving from a base class, or of aggregating and delegating to another component. For example, you could want to make your class cloneable by reusing a mixin:
[Uses (typeof (CloneabilityMixin))]
public class MyCloneableClass
And the test:
public void MyCloneableClass_IsICloneable ()
var instance =
Assert.That (instance, Is.InstanceOfType (typeof (ICloneable)));
(We will look at the actual implementation of the CloneabilityMixin at a later time.)
That way, the class will always support cloning, the implementation supplied by the mixin has become a part of MyClass’s implementation.
The UsesAttribute supports the following optional parameters:
- IntroducedMemberVisibility: As you know from my feature post, mixins can add interface implementations to the mixed object. By default, the members added by such an interface implementation are explicit implementations, ie. private. If you need those members to be made public, which might make sense in some reflection scenarios, you can do so by specifying MemberVisibility.Public to the attribute.
- AdditionalDependencies: I will write about dependencies in another post, but for now it should be enough to say that mixins can have dependencies on other mixins, either directly or indirectly. Dependencies influence the base call order when more than one mixin overrides the same members, and they also define what a mixin can rely on when it accesses the mixed object. Explicit dependencies can be defined via this parameter by passing an array of mixin types to the attribute.
- SuppressedMixins: By default, every target class inherits the mixins configured for its base classes. Sometimes, however, a class might want to replace an inherited mixin with another one – so the new mixin declaration needs to suppress a previous one. Which is what this attribute parameter is for.
Uses is nice, but you could argue that you could replace it simply by having your class hold an instance of the mixin and delegate to it, or even by deriving your class from the mixin. In reality, that “simply” will usually not be so simple at all, because delegation quickly becomes cumbersome and lengthy, and base classes are scarce (only one per class) in the .NET world. Still, let’s look at something you can’t do that easily with manual delegation or inheritance.
A mixin can choose its target classes
Consider scenario (2) from my usage scenario post: you have a finished class model, but need to adapt it. How do you do that?
That’s easy – just create a mixin specifically for those target classes you need to adapt:
[Extends (typeof (MyClass))]
public class MyMixin
Now, while this might seem to be only an inversion of the example given above, semantically it’s much more: It allows a mixin to extend a class from the outside. So, if we follow the base class analogy, this would be like specifying the base of a class from the outside. Try this in C# 🙂
To give a more realistic example, consider a scenario where you have a pre-implemented file management domain, and you have a client requirement to number files in a specific format. While you could simply derive from the pre-implemented File class to add that information (and hope your domain uses inversion of control to instantiate its File objects…), consider that your domain might already contain CarFile, PersonFile, and other subclasses of File. That would quickly result in a subclassing orgy, and all of the subclasses would hold the same delegation code!
So, how to do this, then? Remember, classes automatically inherit mixins from their base classes, so if we implement mixin for this, it should be much more efficient. And it is:
[Extends (typeof (File))]
public class NumberedFileMixin : INumberedFile
private readonly string _id = Guid.NewGuid ().ToString();
public string GetFileNumber ()
And the test for this:
public void File_IsNumbered ()
var numberedFile = (INumberedFile)
var numberedCarFile = (INumberedFile)
var numberedPersonFile = (INumberedFile)
Assert.That (numberedFile.GetFileNumber (),
Assert.That (numberedCarFile.GetFileNumber (),
Assert.That (numberedPersonFile.GetFileNumber (),
(Note that I needed to cast to INumberedFile because the C# compiler can’t know that File now implements INumberedFile via a mixin. There are ways to avoid the cast, but that will go into a separate blog post…)
The ExtendsAttribute supports the same optional arguments as the UsesAttribute does (IntroducedMemberVisibility, AdditionalDependencies, and SuppressedMixins), plus one:
- MixinTypeArguments: Consider the case where you have a generic mixin (if you can’t imagine this, take a look at Stefan’s blog post about mixins in domain design). re-motion’s mixin implementation has an algorithm that tries to supply the type arguments automatically when the mixin is instantiated, but sometimes, the algorithm won’t be able to figure out what you want. In these cases, you’ll need to specify the type arguments by hand using this attribute. (Prize question: Why doesn’t the UsesAttribute need this parameter?)
So, you use the ExtendsAttribute when you write a mixin for specific target classes, and you use the UsesAttribute when you write a class using a specific mixin. Can there be anything else?
Well, what if you want both classes and mixins to be fully oblivious of each other?
An application can combine mixins and classes
Say, for example, you reference a DLL with a finished class model, and you also have a catalog of adaptation mixins for different client scenarios. Now, in your application, you just need to combine the relevant mixins with the respective domain classes. re-motion also supports this:
[assembly: Mix (typeof (MyClass), typeof (MyMixin))]
In this case, the programmer has chosen (via an assembly-level attribute) that instances of MyClass should be mixed with MyMixin in the context of the application. Let’s apply the same to the file numbering sample from above:
[assembly: Mix (typeof (File), typeof (IdentifiedObjectMixin))]
And the test:
public void File_HasID ()
var numberedFile = (IIdentifiedObject)
var numberedCarFile = (IIdentifiedObject)
var numberedPersonFile = (IIdentifiedObject)
Note that I’ve renamed the mixin and the interface to denote a more general mixin implementation. This is exactly the point: the MixAttribute allows you to combine completely general (or “oblivious”) classes and mixins.
The attribute accepts the same properties as the UsesAttribute (IntroducedMemberVisibility, AdditionalDependencies, and SuppressedMixins), plus one:
- MixinKind: Now, what’s that? This parameter takes an Enum value that allows you to choose: do you want to regard the mixin to be extending the target class, or the class to be using the mixin? That’s not really important from the point of view of the mixin engine, but there might be user code that needs to differentiate between these two scenarios. And for such user code, you can specify the relationship. (The default is MixinKind.Extending, by the way.)
So, to wrap it up, re-motion offers three forms of attribute-based declarative mixin configuration:
- The UsesAttribute, by which a class can include mixins, which is similar to inheritance,
- the ExtendsAttribute, by which a mixin can extend a class, which is good to adapt classes from the outside, and
- the MixAttribute, by which an application programmer can combine any class with any mixin.
Use them wisely, and you shall prevail.
Next time: Probably something short about mixins and inheritance.
Edit: You can find the code for this blog entry here:
The tests are here: