0
votes

I have a situation where I need to get a concrete class by name from an open generic base class.

My class hierarchy :

public class Foo { }

public class Bar { }

public abstract class OpenGenericBaseClass<T> where T : class { }

public class ConcreteClass1 : OpenGenericBaseClass<Foo> { }

public class ConcreteClass2 : OpenGenericBaseClass<Bar> { }

My registry code:

For(typeof(OpenGenericBaseClass<>)).Use(x => x.GetInstance<ConcreteClass1>());

For(typeof(OpenGenericBaseClass<>)).Add(x => x.GetInstance<ConcreteClass2>()).Named("Class2");

My program code:

 ObjectFactory.Configure(
            x => x.Configure(
                a => a.Scan(
                    b =>
                    {
                        b.AssembliesFromApplicationBaseDirectory();
                        b.LookForRegistries();
                    })));

        var c1 = ObjectFactory.GetInstance(typeof(OpenGenericBaseClass<>));

        var c2 = ObjectFactory.GetNamedInstance(typeof(OpenGenericBaseClass<>), "Class2");

The first call to GetInstance method (for c1) return a good "ConcreteClass1" object. However for the second call (for c2) I get an exception: StructureMap Exception Code: 200 Could not find an Instance named "Class2" for PluginType TestStructureMapGeneric.OpenGenericBaseClass`1

How can I get my c2 named concrete instance ?

Thanks for your help.

1

1 Answers

0
votes

It seems that StructureMap doesn't support adding named configuration to open generic types. However, why do you need an open generic type ? Open generic types are used in StructureMap to transfer the generic arguments from one class to the other, that's why you can't use the For(typeof(OpenGenericBaseClass<>)).Use(typeof(ConcreteClass1)) construct without getting an exception and have to use a lambda.

For this particular example, I can resolve the types just by adding a base class without using an open generic type :

 public abstract class BaseClass {}
 public abstract class OpenGenericBaseClass<T> : BaseClass where T : class {}

And use the following Registry code :

 For<BaseClass>().Use<ConcreteClass1>();
 For<BaseClass>().Add<ConcreteClass2>().Named("Class2");

Now, I can resolve the instances easily with this code :

 var c1 = ObjectFactory.GetInstance<BaseClass>(); // of type ConcreteClass1
 var c2 = ObjectFactory.GetNamedInstance<BaseClass>("Class2"); // of type ConcreteClass2