StructureMap using named instance during initialize in scanned assemblies in ASP.Net MVC4

I work on a project which use StructureMap as dependency injection manager in a C# Asp.Net MVC4 context.

Basically the structure of the project is a library project (we’ll call it Assembly 1) and a Web project (we’ll call it Assembly 2) which references the library project.

At some point I needed to register named instances in structuremap in the library project Assembly 1 and then use them in the web project Assembly 2.

If you’re in hurry here the working answer in order to have everything working without explanations:


//Assembly 1
public class MyRegistry : Registry
{
    private MyRegistry()
    {
        For().Add(new MyStuff()).Named("myInstance");           
    }
    public static void Setup()
    {
        MyRegistry initializer = new MyRegistry();
        ObjectFactory.Initialize(x =>
        {
            x.AddRegistry(initializer);
            x.Scan(y =>
            {
                y.AssembliesFromApplicationBaseDirectory();
                y.LookForRegistries();
            });

        });
    }       
}

//Assembly 2
public class MySubRegistry : Registry
{
    public Initializer()
    {
        //For().Use().Ctor("config").Is(ObjectFactory.GetNamedInstance("myInstance"));//Doesn't work
        For().Use().Ctor("config").Is(x => x.ConstructedBy(y => ObjectFactory.GetNamedInstance("myInstance")));//This work
    }       
}

Long(er) version

So you want to register named instances in the main registry, you want to use them in some other registries in a sub-assembly and you want to register other stuff in your sub-registry.

An approach could be to scan other assemblies after the container is initialized (example below).


//Assembly 1
public class MyRegistry : Registry
{
    private MyRegistry()
    {
        For().Add(new MyStuff()).Named("myInstance");           
    }
    public static void Setup()
    {
        MyRegistry initializer = new MyRegistry();
        ObjectFactory.Initialize(x =>
        {
            x.AddRegistry(initializer);
        });
        initializer.Scan(y =>
        {
            y.AssembliesFromApplicationBaseDirectory();
            y.LookForRegistries();
        });
    }       
}

This might works for you to use named instances elsewhere in your project but, from a bad experience I had, if after you add some instances (named or not) of some interfaces in a scanned registry they will not be registered.


//Assembly 2
public class MySubRegistry : Registry
{
    public Initializer()
    {
        //With the scan made outside the initialize the named instance can be retrieved as structuremap is already initialized
        For().Use().Ctor("config").Is(ObjectFactory.GetNamedInstance("myInstance"));
        //But this one will never be registered as structure is already initialized
        For().Add(new MyObject());
    }       
}

Thus the only way in order to have everything works is (as described at the top of this article) to scan other registries at structuremap initialisation time AND in scanned registries to use delegate to access things registered in the main registry.


//This
For().Use().Ctor("config").Is(x => x.ConstructedBy(y => ObjectFactory.GetNamedInstance("myInstance")));
//Instead of
For().Use().Ctor("config").Is(ObjectFactory.GetNamedInstance("myInstance"));

Indeed the delegate here will be lazy evaluated. So when it will be evaluated everything would have been registered.
This is really tricky, it worked for me and I hope it will work for you as well.

If you have question or something to fix in the code of this article feel free to comment 🙂

Advertisements
This entry was posted in asp.net, C# and tagged , , , . Bookmark the permalink.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s