Lets say I have the following service and components:
public interface IService
{
void DoWork();
}
public class ServiceA : IService
{
private readonly s
As you say, your two individual requirements are natively supported by AutoFac.
However, there doesn't appear to be direct support for using these two constructs together. I.e. the following does not work:
public enum ServiceType
{
ServiceA,
ServiceB
}
public class MyComponent
{
public MyComponent(Func<string, IIndex<ServiceType, IService> factory)
{
var service = factory("some_string")[ServiceType.ServiceA];
}
}
My work around for this has always been to move the resolution of the service to a factory per service implementation. This then works as follows:
Heres a rough-and-ready example. Note the multiple factories could be reduced to a single generic factory - but I've left it as-is for clarity:
Service implementations
public enum ServiceType
{
NotSet,
ServiceA,
ServiceB
}
public interface IService
{
string DoWork();
}
public class ServiceA : IService
{
private readonly string _name;
public ServiceA(string name)
{
_name = name;
}
public string DoWork()
{
throw new NotImplementedException();
}
}
public class ServiceB : IService
{
private readonly string _name;
public ServiceB(string name)
{
_name = name;
}
public string DoWork()
{
throw new NotImplementedException();
}
}
Service factories
public interface IServiceFactory
{
IService Create(string name);
}
public class ServiceAFactory : IServiceFactory
{
private readonly Func<string, ServiceA> _factory;
public ServiceAFactory(Func<string, ServiceA> factory)
{
_factory = factory;
}
public IService Create(string name)
{
return _factory(name);
}
}
public class ServiceBFactory : IServiceFactory
{
private readonly Func<string, ServiceB> _factory;
public ServiceBFactory(Func<string, ServiceB> factory)
{
_factory = factory;
}
public IService Create(string name)
{
return _factory(name);
}
}
Service registrations
builder.RegisterType<ServiceA>().As<ServiceA>();
builder.RegisterType<ServiceB>().As<ServiceB>();
builder.RegisterType<ServiceAFactory>().Keyed<IServiceFactory>(ServiceType.ServiceA);
builder.RegisterType<ServiceBFactory>().Keyed<IServiceFactory>(ServiceType.ServiceB);
builder.RegisterType<ComponentWithServiceDependency>().As<ComponentWithServiceDependency>();
Example usage
public class ComponentWithServiceDependency
{
private readonly IService _service;
public ComponentWithServiceDependency(IIndex<ServiceType, IServiceFactory> serviceFactories)
{
// Resolve the ServiceB service implementation,
// using the string "test" as its constructor dependency
_service = serviceFactories[ServiceType.ServiceB].Create("test");
}
public string Test()
{
return _service.DoWork();
}
}
You can use Interface Segregation.
public interface IService
{
void DoWork();
}
public interface IServiceA : IService
{
}
public interface IServiceB : IService
{
}
public class ServiceA : IServiceA
{
private readonly string _name;
public ServiceA(string name)
{
_name = name;
}
public void DoWork()
{
//ServiceA DoWork implementation
}
}
public class ServiceB : IServiceB
{
private readonly string _name;
public ServiceB(string name)
{
_name = name;
}
public void DoWork()
{
//ServiceB DoWork implementation
}
}
Then, you can inject delegate factories like so:
public class ClientA
{
public ClientA(Func<string, IServiceA> serviceAFactory, Func<string, IServiceB> serviceBFactory)
{
this.serviceAFactory = serviceAFactory;
this.serviceBFactory = serviceBFactory;
}
public CreateServices()
{
var runTimeName = "runTimeName";
var serviceA = this.serviceAFactory(runTimeName);
var serviceB = this.ServiceBFactory(runTimeName);
}
}
Autofac will generate a delegate factory for each interface you register:
public class MyModule : Module
{
protected override void Load(ContainerBuilder builder)
{
builder.RegisterType<ServiceA>()
.As<IService>()
.As<IServiceA>();
builder.RegisterType<ServiceB>()
.As<IService>()
.As<IServiceB>();
}
}