This article summarizes some thoughts about the potentials of PostSharp with Dependency Injection frameworks. The aim is to support some ongoing or future discussions about loose integration of PostSharp into major DI frameworks. It does not describe something that already exist "off-the-shelf" as a downloadable plug-in.

Container or Service Locator

Most dependency injection (DI) frameworks today require instances to be constructed using a "factory", "object builder" or "container".

This approach also uses a lot of System.Reflection to set up properties. And eventually "bad" reflection: the one that breaks the object encapsulation and accesses private members. You may care or not. I do.

Another major drawback of the "factory" approach is that you cannot use the standard constructors.

This may be just annoying, but can become really blocking if your constructor is called from a part of the program that you don't have control on. For instance, what is you want to inject dependencies into a WinForms user object? When the user object will be added into a form, Visual Studio will instantiate it using the default constructor.

Anyway, why does the consumer of an object need to know that a special factory method should be used? Is our abstraction so shiny?

Of course, there is a solution: inside the constructor, initialize each dependency by a call to a service locator. It is not literally an "injection" of dependencies: dependencies are created from outside.

Container or Context

How does the service locator know how to create the dependency? Where does it take the configuration from, since the object got no reference to its container? Well, actually, the object has no container! The service locator has simply context-sensitive configuration. Each thread has its own context from which the service locator know how to create the dependency. Even better than contexts, stacks of contexts allow to have nested contexts just like we have nested transactions.

An elegant solution is to distinguish between global contexts (static ones) and local contexts (thread-specific). When a dependency is resolved, the service locator always looks for a match from the top of the context stack to the bottom. The stack of local contexts is always on the top of the stack of global contexts.

The use of local contexts makes it possible to execute unit tests in multiple threads while using different mocking implementations of dependencies.

For instance, the configuration of a local context may look like this:

using ( new LocalContext("Test") )
{
    Context.CurrentContext.Bind<ICustomerProcesses>().To<CustomerProcesses>();
    Context.CurrentContext.Bind<IRentalProcesses>().To<RentalProcesses>();

    TestRental test = new TestRental();
    test.Go();
}

Et PostSharp dans tout ça?

The drawback of the Service Locator pattern is that you need to write boiler-plate code. For each field, you have to call the service locator.

This is true for those who don't know PostSharp. But friends of aspect-oriented programming surely noticed an opportunity to let the machine generate code for you!

Wouldn't it be nice to be able to declare a dependency just like this:

class CustomerProcesses : ICustomerProcesses
{
    [Inject]
    private IRentalProcesses rentalProcesses;
}

Wouldn't it be nice to have a custom attribute that adds in all constructors calls to the service locator?

Well, for those who are comfortable with PostSharp Core, it is a matter of hours to develop it. Users of PostSharp Laos will unfortunately have to wait until they get an off-the-shelf implementation. But, promised, it will come soon!

What it means for Dependency Injection frameworks?

What does it mean for DI frameworks to be compatible with this approach?

  • First, they should provide an entry point for "service location", i.e. a method like this:
    T GetDependency<T>( RuntimeFieldHandle field,
                              object declaringInstance )
  • Second, their concept of container should be compatible with the idea of context. Ideally, they should support nesting and default/implicit container for the current thread (or globally).
  • They should have a reasonable API for the aspect weaver to understand their semantics. That is, given a FieldInfo, the DI framework should be able to tell the weaver if the field is a dependency, and if yes of what kind, so that the weaver can decide (at compile-time) if a service location method should be called at runtime, and which. Or better: given a Type, return a list of fields and properties that should be initialized, methods to be called, events to be published or subscribed to...

Apart from these relatively small side requirements (only container nesting is a little extravagant, but it's a nice-to-have both for the container- and the context- based approach), the use of an aspect weaver does not interfere too much with the design of the DI framework. So it is perfectly possible to have to have a DI framework that is AOP-enabled, but still excellent without AOP.

In this presentation from QCon San Francisco 2007, SpringSource CTO and AspectJ project lead Adrian Colyer discusses where Aspect-Oriented Programming (AOP) should be used, practical applications of AOP in enterprise situations such as Hibernate exception translation and automatic operation retry on nonfatal exceptions, and AOP mechanisms in Spring 2.5.

Watch Using AOP in the Enterprise (62 minutes).

[from infoQ.com]

If you already use PostSharp Laos in any project, internal or external, I would like to hear from you and there is a chance for your company to get some (limited) visibility!

I am writing an article for the AOSD 2008 conference and I would like to augment my paper with case study (in technical, not commercial wordings). The case study will then be published separately on the website and eventually mentioned at other conferences.

So, if you think you did something interesting with PostSharp, please get back to me, I really need your feedback!

Thank you,

Gael

PostSharp Blog | PostSharp Community Survey 2009

As PostSharp 1.0 is now released and stable, as PostSharp 1.5 is feature-complete, it's now time to get back to you, community, and ask your opinion about what has been done and which improvements you would like to see in PostSharp 2.0.

That's the reason  of the PostSharp Community Survey 2009 and I expressly invite you to complete it today.

The survey has many objectives:

  • Knowing who you are;
  • Understanding how you are using PostSharp;
  • Measuring your satisfaction;
  • Listening your expectations;
  • Evaluating the commercial potential of PostSharp 2.0 Pro (however it will be named).
  • Last and not least build a public list of customers and collect testimonials.
It should take only 5 minutes to fill in the form. You can take the survey fully anonymously if you want. And if you ever wonder how to contribute to the project... your feedback will definitively help the project!
 
I finish with some good news: as I wrote, PostSharp 1.5 is nearly ready (all bugs are corrected; I still need to write the doc) and we have started working on PostSharp 2.0. I say "we", because some great talent accepted to help me for that release. I'll give details once there will be something tangible to show.
 
Happy PostSharping, and please complete the survey.
 
-gael 

 

Comments are closed