Evaluation for compile-time MSIL enhancement

Feb 23, 2008 at 12:18 PM
I have briefly looked at Unity to evaluate the possibilities to improve developer experience with Unity thanks to PostSharp-enabled MSIL enhancement. I have expressed some thoughts on my blog (http://www.postsharp.org/blog/2008/01/dependency-injection-naturally.html). To summarize, compile-time MSIL enhancement of assemblies possibly:

  1. enables instantiation using the normal constructor, i.e. does not force to use a factory;
  2. enables the injection of dependencies even into private members, i.e. does not force developers to expose public setters.

Let me evaluate these two points separately.

1. Instantiation using Normal Constructors


The idea is to have a custom attribute modifying class constructors to that they call the BuildUp method. This feature is implemented in the Spring Framework (@Configurable annotation) and uses AspectJ to enhance constructors. The same feature has been ported to the .NET version of the Spring Framework by Thomas Darimont -- and surprise, it uses PostSharp for aspecting. The code is available on http://code.google.com/p/postsharp4spring/. Here is an usage example in Java:

package com.xyz.myapp.domain;
 
import org.springframework.beans.factory.annotation.Configurable;
 
@Configurable
public class Account {
   ...
}

Would this be possible with Unity? I am afraid it would not. Indeed, the implementation relies on the Spring facility ContextRegistry. This facility provides the default container for the current context. With Unity, I am afraid there is no notion of "current context". Of course, it is easy to implement a context registry as a side project, but I consider that this concern should be solved by the Unity framework, so there won't be competing implementations. The registry facility should be unique to be useful.

I must say I have been surprised by the complexity of Unity source code. It is really a maximalist approach, with a lot more extensibility than one would expect from a "lightweight container".


2. Initialization of private members.


The idea here would be to be able to set private fields or properties, or invoke private methods, from the IoC framework. The principal advantage of this would be to better respect the object encapsulation and invariant enforcement. Ideally, an IoC framework should not push design changes, like visibility enlargement, into programs that use it.

The technical solution would be that the object would invoke the IoC framework for each field or property marked with the Dependency and would ask to which value it should be assigned. So the IoC framework does not assign or invoke anything on the object being built, it acts purely passively and provides the depedencies to the caller.

Well, having quickly looked at Unity source code, it seems impossible or unreasonable to implement this. Actually, I was surprised by the complexity of Unity. It's design is very maximalist, with much more extension points than I would expect from a "lightweight IoC framework". More concretely, the process if setting dependencies burried too deeply and split into too many classes so that it would be possible (or reasonable) for the IoC facade to offer fine-grained methods besides the coarse-grained BuildUp family. I may be wrong, of course - this is only the result of a first analysis.

So to conclude: I give up the fine-grained initialization, but if there were a context registry in Unity, I would be glad to implement a Spring-like Configurable attribute -- and it would be easy and clean.
Feb 23, 2008 at 3:44 PM
AFAIK, in order to do Private Member Initialization, you need to:

- Add a "DynamicMethodFieldSetterStrategy" to the container BuildPlanStrategies list.
- Add an IFieldChooserPolicy and and in implementation that looks through private fields (exactly the same way PropertyChooserPolicy works!)

And voilà!

Feb 23, 2008 at 6:26 PM


gfraiteur wrote:
I have briefly looked at Unity to evaluate the possibilities to improve developer experience with Unity thanks to PostSharp-enabled MSIL enhancement. I have expressed some thoughts on my blog (http://www.postsharp.org/blog/2008/01/dependency-injection-naturally.html). To summarize, compile-time MSIL enhancement of assemblies possibly:

  1. enables instantiation using the normal constructor, i.e. does not force to use a factory;
  2. enables the injection of dependencies even into private members, i.e. does not force developers to expose public setters.

Let me evaluate these two points separately.

1. Instantiation using Normal Constructors


The idea is to have a custom attribute modifying class constructors to that they call the BuildUp method. This feature is implemented in the Spring Framework (@Configurable annotation) and uses AspectJ to enhance constructors. The same feature has been ported to the .NET version of the Spring Framework by Thomas Darimont -- and surprise, it uses PostSharp for aspecting. The code is available on http://code.google.com/p/postsharp4spring/. Here is an usage example in Java:

package com.xyz.myapp.domain;
 
import org.springframework.beans.factory.annotation.Configurable;
 
@Configurable
public class Account {
   ...
}

Would this be possible with Unity? I am afraid it would not. Indeed, the implementation relies on the Spring facility ContextRegistry. This facility provides the default container for the current context. With Unity, I am afraid there is no notion of "current context". Of course, it is easy to implement a context registry as a side project, but I consider that this concern should be solved by the Unity framework, so there won't be competing implementations. The registry facility should be unique to be useful.

I must say I have been surprised by the complexity of Unity source code. It is really a maximalist approach, with a lot more extensibility than one would expect from a "lightweight container".


This is an interesting idea, and probably quite doable except for, as you mention, finding which container to use.

However, I find it kind of amusing that you first complain that the container is too heavy, then ask us to add a massive new piece of infrastructure. The definition of "lightweight" is a matter of opinion, but a big part of that to me is minimizing what you need to do to use it. "Contexts" would warp your application architecture a lot more than just "create a container and start using it."

We're not going to build anything like that for Unity. Contributors are welcome to pursue it; to be honest, I expect this kind of infrastructure is independent of what you're putting in the "context" anyway.


2. Initialization of private members.


The idea here would be to be able to set private fields or properties, or invoke private methods, from the IoC framework. The principal advantage of this would be to better respect the object encapsulation and invariant enforcement. Ideally, an IoC framework should not push design changes, like visibility enlargement, into programs that use it.

The technical solution would be that the object would invoke the IoC framework for each field or property marked with the Dependency and would ask to which value it should be assigned. So the IoC framework does not assign or invoke anything on the object being built, it acts purely passively and provides the depedencies to the caller.

Well, having quickly looked at Unity source code, it seems impossible or unreasonable to implement this. Actually, I was surprised by the complexity of Unity. It's design is very maximalist, with much more extension points than I would expect from a "lightweight IoC framework". More concretely, the process if setting dependencies burried too deeply and split into too many classes so that it would be possible (or reasonable) for the IoC facade to offer fine-grained methods besides the coarse-grained BuildUp family. I may be wrong, of course - this is only the result of a first analysis.

So to conclude: I give up the fine-grained initialization, but if there were a context registry in Unity, I would be glad to implement a Spring-like Configurable attribute -- and it would be easy and clean.



Actually, this would be pretty easy in the present of Postsharp, which I assume you're talking about using. All that would be needed would be to add the "ContainerAwareStrategy" back into the strategy chain. The original OB had a BuilderAwareStrategy which would call back into the object being built up. We could do something similarly.

You should, using PostSharp, be able to add an implementation of IContainerAware to the object being built up. When you get the "OnBuildup(IUnityContainer container)" call, your generated implementation of OnBuildUp would do what you describe: loop through the dependencies, call the container to get values, and set them. This is actually pretty easy.

-Chris
Feb 23, 2008 at 6:46 PM
Chris,

I'm curious as to why you recommend using IBuilderAware instead of hooking into the BuildPlanStrategies list as I've proposed
Feb 23, 2008 at 6:54 PM
Edited Feb 23, 2008 at 6:55 PM
@Francois/5:44 PM:

Exact. I ignored that DynamicMethod could be associated to a type and therefore have access to private members.
In this case I acknowledge compile-time weaving is of limited interest.

Gael


francois_tanguay wrote:
AFAIK, in order to do Private Member Initialization, you need to:

- Add a "DynamicMethodFieldSetterStrategy" to the container BuildPlanStrategies list.
- Add an IFieldChooserPolicy and and in implementation that looks through private fields (exactly the same way PropertyChooserPolicy works!)

And voilà!



Feb 23, 2008 at 7:08 PM
To play with words, I did not complain, I expressed my surprise :). Just a matter of expectation mismatch.

The problem with contributed context registries is the lack of unity (!). Suppose I want to call BuildUp from the constructor of an ASP.NET page. If I understand well, I have to do my custom "context registry", probably with a single application-wide container stored in a static field. Now what if another part of the project uses PostSharp-booted build-up? If the PostSharp aspect relies on its own registry, there will be two context registries: the one of PostSharp, and the custom one.

As far as PostSharp is concerned, a solution is to define an interface IUnityContainerProvider and to let the developer specify (globally or for each class) an implementation:

interface IUnityContainerProvider
{
  UnityContainer CurrentContainer { get; }
}

Even without context registries, it will be straightforward to adapt Thomas Darimont's aspect to Unity. Do you have already an UnityContrib project ;) ?

Gael
Feb 24, 2008 at 12:54 AM

francois_tanguay wrote:
Chris,

I'm curious as to why you recommend using IBuilderAware instead of hooking into the BuildPlanStrategies list as I've proposed


It was mainly based on the original proposed implementation, but there's a small issue about hooking the build plan strategies. The chooser runs at "compile" time, so it is not a method generated on the target class. That means you need private reflection permissions to run. Not insurmountable, but not something that we would recommend requiring. That and I'm not 100% sure that the dynamic methods we're generating actually have access to private stuff; I'll have to check.

Since Postsharp lets you rewrite the target object's IL arbitrarily, it seemed to be easier to me to have Postsharp generate the code to assign field values; all it needs is a way to kick it off, which is where ContainerAwareStrategy comes into play.

It's actually nice to know there's more than one way to do this.

-Chris
Feb 24, 2008 at 7:41 AM
Note that there is currently no high-level (PostSharp Laos) facility to initialize fields. One has to play with MSIL-level manipulations (using PostSharp Core). So I would need to develop this high-level block. Although it is not difficult, it is not trivial. So I would do it only if there I see some interest, but I cannot see it now. I had a workshop with Spring.NET guys recently, and they weren't really excited by the possibility.

Another point related to the Configurable custom attribute. There could be a problem: suppose that I enrich the constructor so that it calls BuildUp(). A problem occurs if the built object is itself a dependency of another object, because in this case the constructor may be invoked from inside Unity. There are actually two problems:

1. How do I get the relevant container? Even if I have something like a context registry, I must make sure that the dependency will be built using the same container than the parent object. And if there is no framework-provided context registry, how could I get the information? A possibility would be that Unity provides a thread-static property with the container "currently in the stack". Not so nice.

2. We must ensure that the object was not built twice. I suggest to enhance the IBuilderAware interface by a read-only property "IsBuiltUp". PostSharp would implement IBuilderAware automatically.

BTW, another advantage of AOP-enhanced IoC is that dependencies are already initialized in the constructor. It makes it useless to implement IBuilderAware to perform "two-stage" initialization, when the second stage should be performed after dependency injection. That's one of the reason why I wrote that AOP-enhanced IoC allow for a more "natural" programming style, because one does not have to change the design specifically for the IoC framework.

Gael