我有一个IFileSystemService
界面,它定义了一组文件&目录管理功能。它有一个实现,并由Autofac注入需要它的控制器。
但是,由于我们无法控制的原因,我们现在要求将网站的一个特定部分移动到使用数据库而不是文件系统,同时保持相同的功能(即" lite"使用数据库进行存储的文件系统版本)。为此,我创建了IFileSystemService
的第二个实现,它与DB一起使用而不是实际的文件系统。
但是,我无法弄清楚如何告诉Autofac在需要它的特定控制器上使用第二个实现,同时将原始实现保留为所有其他实现的默认实现。
答案 0 :(得分:1)
服务可以被命名为#34;在AutoFac中按https://code.google.com/p/autofac/wiki/TypedNamedAndKeyedServices
将IFileSystemService
的Db实现注册为命名实例:
builder.Register<MyDbFileSystemService>().Named<IFileSystemService>("DbFileSystemService");
然后让依赖控制器使用命名注册:
builder.Register(c => new MyControllerWithDbDependency(c.Resolve< IFileSystemService >("DbFileSystemService")))
.As<Controller>()
.etc
如果更新的问题由于大量额外依赖项而无法实现,我会执行以下操作之一:
IFileSystemService Factory
public class MyControllerWithDbDependency : Controller
{
MyControllerWithDbDependency(IFileSystemServiceFactory fileSystemServiceFactory,
ISomeOtherDependency ...)
{
_service = fileSystemServiceFactory.Create("MyDbFileSystemServiceFactory");
}
}
public interface IFileSystemServiceFactory
{
IFileSystemServiceFactory Create(string dependencyName);
}
public class AutoFacFileSystemServiceFactory : IFileSystemService
{
private readonly IComponentContext _componentContext;
public AutoFacFileSystemServiceFactory(IComponentContext componentContext)
{
if (componentContext == null) throw new ArgumentNullException("componentContext");
_componentContext = componentContext;
}
public IFileSystemService Create(string dependencyName)
{
return _componentContext.ResolveNamed<IFileSystemService>(dependencyName);
}
}
即。每个控制器负责指定它所需的特定IFileSystemService
依赖关系,这反过来意味着不会更改控制器的AutoFac配置。
老实说,我通常只在需要解决的特定类型直到运行时才知道的情况下使用这种技术 - 不像在问题中它将用作解决方法。
显然,如果你有大量的控制器和一小组IFileSystemService
实现,并且从设计的角度来看它是有意义的,你可以将工厂的Create
调用推送到自定义控制器基类型,并保存自己一些代码重复。
将IFileSystemService的特定实现注册为自己的服务
public class MyControllerWithDbDependency : Controller
{
MyControllerWithDbDependency(MyDbFileSystemService dbFileSystemService,
ISomeOtherDependency ...)
{
// ...
}
}
// AutoFac configuration
builder.RegisterType<MyDbFileSystemService>()
.As<MyDbFileSystemService>()
.InstancePerWhatever();
builder.RegisterType<DefaultFileSystemService>()
.As<IFileSystemService>()
.InstancePerWhatever();