Oliver
Oliver

Reputation: 172

StructureMap Open Generics Use Based on Derived Type

I have two entity base classes:

public abstract class EntityBase { }
public abstract class ClientSpecificEntityBase : EntityBase

and two categories of entities:

public class Thing : EntityBase { }
public class ClientSpecificThing : ClientSpecificEntityBase { }

and two types of services, which both implement IService<T>

ServiceBase<T> : Service<T> where T : EntityBase
ClientSpecificServiceBase<T> : ServiceBase<T> where T : ClientSpecificEntityBase 

I'm using the following code to configure StructureMap:

_.For(typeof(IService<>)).Use(typeof(ServiceBase<>));
_.For<IService<ClientSpecificEntityBase>>().Use<ClientSpecificServiceBase<ClientSpecificEntityBase>>();

But everytime I try to access IService<ClientSpecificThing>:

public ClientSpecificThingController(IService<ClientSpecificThing> service)

I am getting ServiceBase<ClientSpecificThing> rather than ClientSpecificServiceBase<ClientSpecificThing>

Is there any way to get StructureMap to include the derived types when it maps ClientSpecificServiceBase<T>?

Upvotes: 0

Views: 152

Answers (1)

Scott Hannen
Scott Hannen

Reputation: 29302

No, you can't do what you're trying to do. The container isn't going to look through the registered components for base classes of generic types.

This becomes more apparent if you remove the first registration, leaving only

_.For<IService<ClientSpecificEntityBase>>()
    .Use<ClientSpecificServiceBase<ClientSpecificEntityBase>>();

Now, if you call

var resolved = container.GetInstance<IService<ClientSpecificThing>>();

You'll get an exception:

StructureMap.StructureMapConfigurationException: No default Instance is registered and cannot be automatically determined for type 'IService'

So it's not that StructureMap is confused between the two registrations and is returning the wrong one. It doesn't recognize that when you register this:

IService<ClientSpecificEntityBase>

that it can use that fulfill this because one generic type inherits from the other.

IService<ClientSpecificThing>

Upvotes: 1

Related Questions