1
votes

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?

1
have a look at - DocumentationPreet Singh
In this documentation page they explicitly register concrete implementations, but I don't want to do that, as I say in my last statement.Arturo Ribes
how did you know it instantiated DataService and not ClientService.did you check that its calling your overrides, just sanity check. Actually you are registering DataService as concrete for IDataservice and thats what structuremap is giving you when you ask for it. I think you need to have a look at your inheritance chain again.might have to go down This routePreet Singh

1 Answers

1
votes

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>>();