Composite Oriented Programming spike on Unity Application Block

Suddenly the coolness of Qi4j starts seeping into the .NET community. There are now several proofs of concept available. And here is one more. smile_regular There are two major differences with this post compared to the other ones out there:

  1. This spike does not rest upon the obvious and very suitable Castle project. This implementation uses another DI framework which I've learn to use and really like. It is not as evolved for sure but neither is it HUGE and complex. I used the Unity Application Block from Patterns & Practices.
  2. I go ahead and tackle the problems surrounding .GetType(). Perhaps this has a solution in Castle already?

I've attached my code to this post!

Recognition

First I'd like to recognize three separate spikes on this concept: Hendry Luk - Roll Your Own COP, Yves GoEleven.com - Cop - Proof of concept and Anders Norås - Trick or Trait? Composite Oriented Programming with C#.

My Spike

I started with getting Unity up and running and calling out at a point I deemed useful to create composites. Then I implemented basic functionality and took it a couple of steps deeper.

The Test Harness

My tests are put in a test harness which has a SetUp (and TearDown) functionality to deliver a new and empty unity container to each test.

[TestFixture]
public class COPStrategyTests
{
    IUnityContainer container;

    [SetUp]
    public void SetUpUnityWithCOPStrategy()
    {
        container = new UnityContainer();
        container.AddNewExtension<CopUnityContainerExtension>();
    }

    [TearDown]
    public void TearDownUnity()
    {
        container.Dispose();
    }

    [Test]
    public void CreateSimpleComposite()
    {
[...]
    }
}

This means I can easily use my container in each following test without bothering with setting it up each time. The interesting thing about it is the CopUnityContainerExtension that I added. What does it do?

Using Unity Application Block

If Unity does not really interest you and you are here to read about COP just skip ahead!

Microsoft has basically intended to black-box the ObjectBuilder(2) which is the engine underneath Unity. I've never seen the ObjectBuilder as a black box since I feel there is way too much fun things you can do with it if you only know how.

First thing you have to understand about the UnityContainer is that it is configured with the concept of extensions to the configuration of the container. All I do is one very simple and strategic thing: I add a so called Strategy to handle composites. Strategies in Unity, or rather in ObjectBuilder, are the links in an execution chain of resolving instances through the container. Each instantiation is passed along the chain from one end to the other and back again. (There is also a reverse chain which may be used to tear down instances rather than building them up.) Each link (strategy) in the chain is responsible for certain behaviors like Dependency Injection, Policy Injection (AOP behavior) and so on.

For our purposes we only need to focus on two links in the standard chain and understand why I add the COP strategy in between.

This is the normal order of type mapping and creation in Unity:

standardUnity (note that there may be any number of links in the chain before, between and after but we are simplifying)

If a contract (interface) is requested to be built up it is type mapped over to a concrete class and this class is passed to creation.

The CopUnityContainerExtension adds a COPStrategy to the chain right in between the type mapping and creation. The reason for this is simple: If a contract does not have a mapping it must be a composite! Since the creation step cannot instantiate interfaces (composite contracts) we have to intercept that part of the functionality and create our composite before the creation step. Creation does not try to create when there already is an existing instance in play in the chain (useful for lifetime managers and singletons for instance). We still, however, want to run the rest of the chain since we can never know what other behaviors might be in the chain that we may want to be part of (Dependency Injection for instance).

This is what the same chain looks like once I've added my COPStrategy by means of the CopUnityContainerExtension.

COPUnity

Now we have a perfect point to insert COP behavior!

Test 1) Basic COP

First I wanted to run a very basic schenario. A contract with one composite part.

[Test]
public void CreateSimpleComposite()
{
    container.RegisterType<CanThink, Einstein>();

    ThinkingPerson person = container.Resolve<ThinkingPerson>();

    Assert.IsNotNull(person);
    Idea idea = person.Think();
    Assert.IsTrue(idea.IsBrilliant);
}

The .RegisterType call is my configuration of the mapping in Unity between a contract and an implementation. Naturally you can configure Unity in all the classic ways including configuration, in code or dynamically. But just to be clear and specific in each test I configure its mappings at the top of each test. In this first test case I am pointing the CanThink contract to the Einstein implementation.

public interface CanThink
{
    Idea Think();
}
public class Einstein : CanThink
{
    public Idea Think()
    {
        return new Idea(true);
    }
}

True means the ideas from this implementation of CanThink are brilliant in nature!

The composite is the ThinkingPerson contract.

public interface ThinkingPerson: CanThink {}

My test turns green and I leave the implementation details for those who are interested in learning how I coded my spike.

Test 2) A little more complex COP

Just a bit more complex but very similar is the next test there the composite looks like this:

public interface ThinkingDancer: CanThink, CanDance {}

The test shows that more than one part in the compositions is also OK.

[Test]
public void CreateMoreComplexComposite()
{
    container.RegisterType<CanThink, Einstein>();
    container.RegisterType<CanDance, JohnTravolta>();

    ThinkingDancer person = container.Resolve<ThinkingDancer>();

    Assert.IsNotNull(person);
    Idea idea = person.Think();
    Assert.IsTrue(idea.IsBrilliant);

    Cred cred = person.Dance();
    Assert.AreEqual(CredLevel.VeryHigh, cred.CredLevel);
}

The test clearly shows that if someone does dance like John Travolta his "Cred Level" is "Very high". It also, more importantly, points out that a ThinkingDancer has both the ability to dance and to think.

Test 3) Injecting parts into one another - ThisAttribute

In order for this sample to become a bit more interesting you just have to add the capability to inject one composition part into another. I chose to allow a ThisAttribute to be declared both on the implementation and, above this, on the contract. I like the idea of declaring that this part requires another part already on the contracts. But I realize that there are times when perhaps you want to do it on the underlying implementation only. My spike does both.

[Test]
public void COPIncludingThis()
{
    container.RegisterType<CanThink, Einstein>();
    container.RegisterType<ReportBrilliance, BrillianceVoice>();

    KnowsSmartness insightful = container.Resolve<KnowsSmartness>();

    string howSmartIAm = insightful.SayHowSmartIAm();

    Assert.AreEqual("I am smart!", howSmartIAm);
}
KnowsSmartness is someone who has a certain level of brilliance and is able to report the fact.
public interface KnowsSmartness : CanThink, ReportBrilliance { }

The interesting part here is the ReportBrilliance contract:

public interface ReportBrilliance
{
    //[This] the attribute and declaration here works if you wish!
    //CanThink CanThink { get; set; }

    string SayHowSmartIAm();
}

And it's implementation:

public class BrillianceVoice : ReportBrilliance {
    [This] // May also be declared on contract if contract specifies the relation
   
public CanThink CanThink { get; set; }

    public string SayHowSmartIAm()
    {
        bool brilliant = CanThink.Think().IsBrilliant;
        return brilliant ? "I am smart!" : "I am dumb!";
    }
}

The position of the ThisAttribute shows that in order to be able to report how brilliant one might be I have to know how I think. CanThink is "injected" into ReportBrilliance by means of the [This] declaration.

Test 4) Adding hierarchies - a composite part is a composite

This is all very cute and cuddly but what happens when a composite is composed of other composites. The think I ran smack into was the fact that the .GetType() method is very peculiar. It is different in the sense that it is marked with [MethodImpl(MethodImplOptions.InternalCall)] which means it is an exception to the rules of .NET. It is handled internally by the CLR. You can by all means new it away and change its implementation:

public new Type GetType()
{
    return typeof(string);
}

But that certainly is asking for trouble since a call like ((object) foo).GetType(); will revert the logic.

What did I need .GetType() for? Well I needed to ask my composites which type they were in order to reflect the properties to find any usage of the ThisAttribute. When I have a composite where a part is a composite I ended up asking the proxy for its type and this does not work! The logical answer would be the type of the interface but it does not have an implementation! In fact the .GetTransparentProxy() call returns the illusive __TransparentProxy which is internal to the .NET core (internal sealed). If you ask this instance what type it is it will forward the call to System.Object. And of course this is not our purpose.

In order to build around this I cheated Big Time and crapped all over my spike code. I'll elaborate here in text but it might be a bit hard to follow unless you look at the code in parallel. Just look at this: If the proxy .Invoke(IMessage) call is a call from the method named .GetType() and referencing the object type. Then we create a faked internal class of type MethodCallMessage that I've hacked myself (GetTypeMethodCallMessage). This fake implementation only implements the few methods and properties that are called in a very naive and static way. I am certainly not 100% certain it holds water. It in turn even has it's own internal class inheriting MethodBase (GetTypeMethod) which answers method related questions. After this initialization of a faked MethodCallMessage i go about my business as usual. The call is forwarded to this new method which naturally will answer with the Type of the contract.

If this was difficult to follow I totally understand. It is a messy cheap implementation with a weak text based explanation.

However it works in this isolated spike! I can ask a __TransparantProxy what type it is through .GetType() and get its contract in return. There naturally exists other ways to work around this issue!

My final test with this approach looks like this:

[Test]
public void COPIncludingThisAndCOPHierarchy()
{
    container.RegisterType<CanThink, Einstein>();
    container.RegisterType<CanDance, JohnTravolta>();
    container.RegisterType<DancingThinker, DancingThinkerDude>();

    Magnus magnus = container.Resolve<Magnus>();

    ImpressiveResults impressiveResults = magnus.JiggyWhileThinking();

    Assert.AreEqual(CredLevel.VeryHigh, impressiveResults.Cred.CredLevel);
    Assert.AreEqual(true, impressiveResults.Idea.IsBrilliant);
}

Magnus (me ;~) and the hierarchy below me has the following layout:

public interface Magnus : GotBrainsAndMoves
{}
public interface GotBrainsAndMoves : DancingThinker, CanThink, CanDance
{}
public interface DancingThinker
{
    [This]
    CanDance Dancer { set; }

    [This]
    CanThink Thinker { set; }

    ImpressiveResults JiggyWhileThinking();
}

Meaning I am amble to .JiggyWhileThinking() procucing ImpressiveResults. The impressive results show Very High Cred Level and Brilliant ideas! ;~)

In other words we are able to have hierarchies of composites including "injection" between parts.

Future of COP on .NET

OK! That was my spike on the matter. Where to next? Just so happens I am fortunate enough to work in the same organization as Rickard Öberg. He works for Jayway and I work for Dotway. Both in the Waygroup. I have every intention to try to commence a porting project for Qi4j into Qi# (great name Anders Norås) as soon as it it freezable. Naturally this initiative is not an announcement! It is more an intent to proceed. I bet others out there are intending the same right about now! Best thing about that is that this is by no means a competition. It is collaborative open source work and we should all get crackin'. ;~)

Why do this? Well to find out if there are any good practical applications on the .NET platform of course and to see if we can do it!

Cheers,

/Magnus

Technorati Tags: ,,,

posted @ Wednesday, August 27, 2008 4:11 PM

Print

Comments on this entry:

# re: Composite Oriented Programming spike on Unity Application Block

Left by Torkel at 8/28/2008 2:50 PM
Gravatar
I was also thinking about porting Qi4j 6-7 months ago when I stumbled upon Qi4j.

It would be great with a .NET port.

# re: Composite Oriented Programming spike on Unity Application Block

Left by Henrik at 9/19/2008 3:17 PM
Gravatar
Tufft! (=cool) I've been thinking about this ever since I first read about Qi4j. It should be possible to combine this into some great code when it comes to DDD and building expressive domain models.

# re: Composite Oriented Programming spike on Unity Application Block

Left by Web developer at 8/17/2009 8:24 PM
Gravatar
Humm... interesting,
Keep up the good work

# re: Composite Oriented Programming spike on Unity Application Block

Left by website chat software at 12/22/2009 10:25 AM
Gravatar
So far, I managed to go though only some of posts you discuss here, but I find them very interesting and informative. Just want say thank you for the information you have shared. Regards

Your comment:



 (will not be displayed)


 
 
 
Please add 6 and 2 and type the answer here:
 

Live Comment Preview: