Archive for the ‘Misc’ Category

StructureMap and the Singleton Scenario

Friday, December 5th, 2008

A few months ago I made the switch from CastleWindsor to StructureMap for my dependency injection needs. It’s a more active project, more up to date with the times, more extensible, and definitely has a better interface for configuring through code rather than xml. After a few growing pains I’ve grown to like it a lot ( I’m using version 2.5). However in the last few days I’ve run into a roadblock it seems, and it all has to do with the lifecycle/scope of objects.

A lot of dependency objects in the typical application could be singletons if designed right (covers head from flames). However there is a point at which that ceases to be the case, that’s where unit of work patterns come into play. A unit of work has only a finite lifespan and should then be disposed. In keeping with good testability and design patterns you will probably also want to have a ready made unit of work object injected into the classes that need them. Every time that you ask for a unit of work you should be supplied with a fresh new copy. That’s where configuring the lifecycles properly in your DI tool should come into play.

As code is a common language, I will code out what I am talking about as simply as possible.

//Think of this as a data session
public class Session
{
}
 
public class Model1
{
    public Session Session { get; set; }
 
    public Model1(Session session)
    {
        Session = session;
    }
}
 
public class Model2
{
    public Session Session { get; set; }
 
    public Model2(Session session)
    {
        Session = session;
    }
}
 
//this is my shell, it needs some models
public class Shell
{
    public Model1 Model1 { get; set; }
    public Model2 Model2 { get; set; }
 
    public Shell(Model1 model1, Model2 model2)
    {
        Model1 = model1;
        Model2 = model2;
    }
}

This is a pretty straight forward scenario. We have a shell (entry point) that contains a couple of models, each of these models requires a unique data session so that it can pull and work with its data independently.

Let’s use StructureMap to wire these together so that we just create our shell and have its dependencies filled for us automatically. Remember that by default StructureMap does not create singletons, so using the default config should result in transient, per-request objects.

ObjectFactory.Initialize(
    x => {
             x.BuildInstancesOf()
                 .TheDefaultIsConcreteType();
             x.BuildInstancesOf()
                 .TheDefaultIsConcreteType();
             x.BuildInstancesOf()
                 .TheDefaultIsConcreteType();
             x.BuildInstancesOf()
                 .TheDefaultIsConcreteType();
    });

Now let’s test to make sure that we have a unique data session.

Shell shell = ObjectFactory.GetInstance();
 
Assert.AreNotEqual(shell.Model1.Session, shell.Model2.Session);

And this is where we come to the fail part. The data session contained in each model is identical, the same as if we had declared it as a singleton. We know that the configuration is right because doing it this way works.

Assert.AreNotEqual(ObjectFactory.GetInstance(), ObjectFactory.GetInstance());

Why this happens has been a matter of great curiosity to me, and even though I’m not a great StructureMap expert I’ll hazard an educated guess. Each time that you make a declarative request for the root of an object graph, StructureMap creates a unique BuildSession. Inside that build session there is a cache of instantiated objects. The session then builds one object for each dependency in the graph no matter how many times it is requested in that graph. The objects may be built or pulled using a variety of methods but once they are built and stored in the graph then they are not requested to be built again for the lifetime of that BuildSession. This means that for a given declarative request you will only ever have one object per type instantiated. If, like me, you are starting your application from a bootstrapper this effectively turns all of your objects into singletons.

Lets try the same scenraio in CastleWindsor.

WindsorContainer container = new WindsorContainer();
 
container.AddComponentWithLifestyle("Session", typeof(Session), LifestyleType.Transient);
container.AddComponentWithLifestyle("Model1", typeof(Model1), LifestyleType.Transient);
container.AddComponentWithLifestyle("Model2", typeof(Model2), LifestyleType.Transient);
container.AddComponentWithLifestyle("Shell", typeof(Shell), LifestyleType.Transient);
 
Shell shell = container.Resolve();
 
Assert.AreNotEqual(shell.Model1.Session, shell.Model2.Session);

This works, both data sessions are unique. Let’s try AutoFac.

var builder = new ContainerBuilder();
 
builder.Register().FactoryScoped();
builder.Register().FactoryScoped();
builder.Register().FactoryScoped();
builder.Register().FactoryScoped();
 
var container = builder.Build();
 
Shell shell = container.Resolve();
 
Assert.AreNotEqual(shell.Model1.Session, shell.Model2.Session);

Again this works as well.

How can this problem be solved by mere mortals? Well the most obvious solution would be to pass factories that can create your transient objects instead of just passing the transient objects themselves. However this is not ideal as it just leads to more code noise that should be handled by the DI component.

Can we use an interceptor? Unfortunately this approach does not work as your custom interceptor will be called only once per BuildSession resulting in the same problem. The same is true for using a ConstructorInstance. As this post ends I have been searching for a way of getting true instanced objects out of structuremap for most of a day with no success. In ending let me say that I am open to any expertise you may offer on this subject, and if I do find the answer I will most definitely post an update to this article.

Update
It would appear that there is no good way to do this using StructureMap. There is a workaround that though arduous could work for more limited scenarios. The trick is to define the dependency for the object that needs a transient type.

x.BuildInstancesOf()
    .TheDefault.Is.OfConcreteType().CtorDependency().Is( x.OfConcreteType() );

Though this works it wouldn’t be really practical if your dependency is used in numerous places. The reasons that the author chose to limit transients to only once per session are valid and advantageous for his situation but causes some problems elsewhere. What I would have preferred was that the BuildSession caching was done with an interceptor the same way as singleton caching. That way not every instance would be limited by the BuildSession caching and other implementations could be provided.

Update

As Bart Deleye pointed out in the comments the latest version of StructureMap now properly supports this scenario with the following syntax.

.ForRequestedType().TheDefaultIsConcreteType().AlwaysUnique()

Thus resulting in a very happy ending due to the flexibility and collaborative nature of open source software.  Thanks Jeremy

kick it on DotNetKicks.com

Forums are here

Thursday, October 23rd, 2008

Due to the number of comments that I have been getting on this blog and the emails that I have been receiving,  I have decided to setup a small forum for questions and comments.  Feel free to drop by and add your 2 cents on NHibernate.Remote, Generic Messaging or just anything in general.  I will try to answer any questions directed to me in a timely fashion (I hope).

Broke and happy, NHibernate 2.0 is out!

Monday, August 25th, 2008

Heh, sorry, the title is a bit misleading because although my cash reserves have been significantly drained by the purchase of a house, I am not broke.  But my code is, now that NH 2.0 has finally been released.  This finally means that I can start programming against solid production code.  However this release is not without its caveats.  NHibernate.Linq has been a project that I have been folowing quite closely and actually using.  Back around the time that Beta 2 of NH 2.0 was released, the NHibernate.Linq project was moved into the NHibernate.Contrib project and relatively quickly lapsed into obsolecence as it has not been able to be built against the releases for some time now.  I was hopefull that by the time 2.0 was actually released that NH.Linq would be caught up, but alas that was not the case.  The reason why is that there is  new, better, and refactored linq support on its way for NHibernate and is scheduled for the 2.1 version of NHibernate.  That’s great and all but it doesn’t really help poor schmoes like me who want to use the existing linq features for now.

Ok that’s enough whining for now, on to the fixing.  The main problem is that criteria queries have lost the property to spit out the name of the persitent class they are linked to.   Also some methods have been added to the ICriteria interface and some things have changed in the factory also to do with persistent class names.  Using my meager NHibernate skills I think I have worked around all these issues except for one (no more criteria comments) and if you are brave enough you can try the dll or apply the svn patch.  All of the tests ran fine for me, but I really havn’t had a chance to play around with it extensively.

This archive includes both a patch for applying to your NHibernate.Linq svn directory, and an NHibernate.Linq dll that is built against NHibernate 2.0GA.

Download at your own risk.

Unit tests, FTW!

Wednesday, June 18th, 2008

I’ve been working on an inventory system for my company and have been encountering a serious amount of resistance from both my neurons and the problem at hand.  So I’m giving the old noggin a brief respite and I’m back to working on NHibernate.Remote.  However my forray into inventory land has taught me some valuable lessons.

  1. Dependency injection is fun, and very usefull when used right.  I’m using the Castle Windsor framework and it seems to be working very well.
  2. Unit tests work and are necessary to ensure proper functioning of your software.

Now some of you may be spewing coffee right about now after reading number 2, because unit tests just seem like such a no brainer right now.  However <whisper>I’m the only one in my company who does them</whisper>.  Anyhow, I am convinced of the need for good unit tests if not completely ready to go straight to TDD.

Anyhow the point of this story is that I am taking some time to write unit tests for NHibernate.Remote, and I expect to find lots and lots of bugs.

Interesting content goes here.

Thursday, February 21st, 2008

After discovering this nifty little blogging software called WordPress, I decided it was time to start my own blog. There is nothing really special behind this decision other than the need to start giving something back to the community that has given so much to me. I will be posting mostly technical things to do with software development, and most of it will be pertaining to .net as that is the language that currently pays the bills.

To kick off this blog I will be starting a series of post on how to use nHibernate sessions remotely over WCF. With support for lazy loading and Dynamic Queries. So stay tuned.