Jeff Treuting
Jeff Treuting

Reputation: 13510

StructureMap 3 get requested type

I have the following StructureMap registrations that work in version 2.6.4 and I'm finally upgrading to the latest SM (3.1.2 as of this writing). And need to update it since there doesn't appear to be a IContext.BuildStack anymore.

Here is the old working version with 2.6.4:

        initialization.For(typeof(IRepository<,>))
                             .Use(context =>
                             {
                                 var genericArgs = context.BuildStack.Current.RequestedType.GetGenericArguments();

                                 return RepositoryFactory.GetInstance(genericArgs[0], genericArgs[1], repositoryName);
                             }
            );

So I figured that changing it to this would work:

        initialization.For(typeof (IRepository<,>))
            .Use("IRepository<,>", context =>
                                   {
                                       var genericArgs = context.ParentType.GetGenericArguments();

                                       return RepositoryFactory.GetInstance(genericArgs[0], genericArgs[1],
                                           repositoryName);
                                   }
            );

But context.ParentType is null. When I look at context.RootType it is set to System.Object which is obviously not what I want.

My test code to get an instance of this repository is:

var userRepository = ObjectFactory.GetInstance<IRepository<User, Guid>>();

I don't see any other property that has this information, but I'm guessing I am missing something.

Upvotes: 3

Views: 590

Answers (2)

Jeremy D. Miller
Jeremy D. Miller

Reputation: 361

I added a new example to the StructureMap 3 codebase for this scenario based on your question:

https://github.com/structuremap/structuremap/blob/master/src/StructureMap.Testing/Acceptance/builder_for_open_generic_type.cs

I have to ask though, what's the purpose of something like RepositoryBuilder if you're using an IoC container?

Anyway, this implementation should be more efficient than the older Reflection-heavy approach.

Upvotes: 4

Robin van der Knaap
Robin van der Knaap

Reputation: 4120

You are not missing something. On GitHub someone posted a simular question: https://github.com/structuremap/structuremap/issues/288. Jeremy Miller, the author of structuremap, responded:

It's going to have to be new development. It'll have to come in a 3.2 version.

The suggested workaround is to create a custom instance and override the ClosingType method. You can do this as follows:

public class CustomInstance : Instance
{
    public override IDependencySource ToDependencySource(Type pluginType)
    {
        throw new NotImplementedException();
    }

    public override Instance CloseType(Type[] types)
    {
        var repository = RepositoryFactory.GetInstance(types[0], types[1], repositoryName);                                                           
        return new ObjectInstance(repository);
    }

    public override string Description
    {
        get { throw new NotImplementedException(); }
    }

    public override Type ReturnedType
    {
        get { return typeof (IRepository<,>); }
    }
}

Now, you only have to connect the open generic type to the closing type like this:

initialization.For(typeof (IRepository<,>)).Use(new CustomInstance());

Upvotes: 6

Related Questions