Reputation: 365
I have a generic interface IDataService<T>
and its default implementation DataService<T>
. Then, some types have their particular service interface, which implement also IDataService
, for example:
public interface IClientService : IDataService<Client>
{
void SomeProcess();
}
public class ClientService : DataService<Client>, IClientService
{
public override SomeDataServiceMethodOverride();
public void SomeProcess();
}
As you can see, ClientService
is a specialised IDataService<Client>
which extends the functionality of DataService<Client>
and also implements another interface.
What I would like is that when I ask to StructureMap for an IDataService<Client>
it gives me a ClientService
, but when I ask for a IDataService<OtherEntity>
just falls back to the default implementation DataService<OtherEntity>
. What I had until now in my StructureMap configuration was:
Scan(
scan => {
scan.AssemblyContainingType<IClientService>();
scan.AssemblyContainingType<ClientService>();
scan.WithDefaultConventions();
});
For(typeof(IDataService<>)).Use(typeof(DataService<>));
but the problem was that it didn't instantiate a ClientService
when asking for IDataService<Client>
, but a DataService<Client>
. Now I changed the last line to:
For(typeof(IDataService<OtherEntity>)).Use(typeof(DataService<OtherEntity>));
But then I have to do that for any entity which does not have a concrete service implementation. How can I do that automatically?
Upvotes: 1
Views: 582
Reputation: 1323
From your description it sounds like you want to register all the interfaces on your concrete service types. StructureMap enables this by providing the ability to define custom conventions that are applied to scan operations. You define a type which implements StructureMap.Graph.IRegistrationConvention
and then define the ScanTypes
method. The method provides the collection of scanned types and the registry that stores your custom configurations.
The following snippet is functionally equivalent of code found in the StructureMap documentation found here.
public class AllInterfacesConvention : StructureMap.Graph.IRegistrationConvention
{
public void ScanTypes(TypeSet types, Registry registry)
{
foreach(Type type in types.FindTypes(TypeClassification.Concretes | TypeClassification.Closed)
{
foreach(Type interfaceType in type.GetInterfaces())
{
registry.For(interfaceType).Use(type);
}
}
}
}
You can then update your scan operation to apply this convention.
var container = new Container(x => {
x.For(typeof(IDataService<>)).Use(typeof(DataService<>));
// Override custom implementations of DataService<>
x.Scan(scanner => {
scan.AssemblyContainingType<IClientService>();
scan.AssemblyContainingType<ClientService>();
scan.Convention<AllInterfacesConvention>();
});
});
// This should now be of type ClientService
var service = container.GetInstance<IDataService<Client>>();
Upvotes: 1