views:

147

answers:

3

Hi

I have an interface something like this:

interface IGenericSetupViewModel<T>

I then have a default implemtation of this, something like this

class GenericSetupViewModel<T> : IGenericSetupViewModel<T>

For some specific classes i have a specific implementation like this:

class ContractSetupViewModel : GenericSetupViewModel<Contract>

Now i want to make StructureMap return the correct instance, when asking for a

ObjectFactory.GetInstance<GenericSetupViewModel<Contract>();

I would like to get ContractSetupViewModel returned, when asking for anything else, i would like to get an instance of

GenericSetupViewModel<T>

I tried doing this:

        StructureMap.ObjectFactory.Configure(x =>
        {
            x.Scan(y =>
            {
                y.TheCallingAssembly();
                y.AddAllTypesOf(typeof(IGenericSetupViewModel<>));
                y.ConnectImplementationsToTypesClosing(typeof(IGenericSetupViewModel<>));
            });
        });

However this results in me always getting a GenericSetupViewModel and never the ContractSetupViewModel. I dont want to have to specify all specific viewmodels so is there anyway i can get this scan to work ?

A: 

In your GetInstance method you should do something like:

if (AnInstance is GenericSetupViewModel)
    return AnInstance as GenericSetupViewModel;
else if (AnInstance is ContractSetupViewModel)
    return AnInstance as ContractSetupViewModel;
James
that is exactly what i dont want to be doing.
Morten Schmidt
It may not be what you want to do but I can't see any other way (off the top of my head). You should perhaps rethink your design if this isn't going to work.
James
+1  A: 

There was a short-lived bug in StructureMap where ConnectImplementationToTypesClosing had trouble if your specific closing type didn't implement the interface directly. Once you get the latest version of StructureMap, the following code will work:

StructureMap.ObjectFactory.Configure(x =>
{
    x.Scan(y =>
    {
        y.TheCallingAssembly();
        y.ConnectImplementationsToTypesClosing(typeof(IGenericSetupViewModel<>));
    });
    x.For(typeof (IGenericSetupViewModel<>)).Use(typeof(GenericSetupViewModel<>));
});
Joshua Flanagan
I tried updating, however this still doesnt work.The code below still always gives me a GenericSetupViewModel<Contract> instead of a ContractViewModel, commenting out as shown results in it not being able to resolve anything. StructureMap.ObjectFactory.Configure(x => { x.Scan(y => { y.TheCallingAssembly(); y.ConnectImplementationsToTypesClosing(typeof(IGenericSetupViewModel<>)); }); //x.For(typeof(IGenericSetupViewModel<>)).Use(typeof(GenericSetupViewModel<>)); });
Morten Schmidt
Look at the following test, that passes with the latest structuremap:http://github.com/structuremap/structuremap/blob/61c4b9b6d968b6bcce0e63fed5079902d0ab956e/Source/StructureMap.Testing/Bugs/CloseOpenGenericsWithSomeSpecifics.csCan you make that test fail? How is it different from your example? Do you have additional registration code that you are not showing, that could potentially be conflicting?
Joshua Flanagan
i found the issue, for the scanner to work the classes need to be public, mine were private.Thanks
Morten Schmidt
A: 

I'm not too familiar with StructureMap but could it be that you are tricked by registration priority?

Since you call y.AddAllTypesOf(typeof(IGenericSetupViewModel<>)); first, this will register the opene generic class GenericSetupViewModel<T> first. This registration will fulfill your resolve request for GenericSetupViewModel<Contract> and the more specific ContractSetupViewModel registration is ignored.

That said, the Flattener sample clearly shows that having a open generic type registration and specific closed generic type registrations should work. Can you get this pattern to work with your types?

Peter Lillevold