我正在考虑从Ninject迁移到Autofac,但我正在努力翻译其中一个有用的功能 - 通过属性约束绑定。
我目前有这个界面和实现:
public interface IRepository
{
IEnumerable<SomeObject> Get();
}
public class DBRepository : IRepository
{
public IEnumerable<SomeObject> Get()
{
// call the database
}
}
我有一个缓存的实现,它将检入缓存,如果没有找到,请调用db存储库。这将传递给构造函数:
[DataNeeded]
public class CacheRepository : IRepository
{
private readonly IRepository dataRepo;
public CacheRepository(IRepository dataRepo)
{
this.dataRepo = dataRepo;
}
public IEnumerable<SomeObject> Get()
{
// check the cache and if nothing found:
return this.dataRepo.Get();
}
}
最后,我有一个调用控制器,它将使用缓存来获取一个对象:
[CacheNeeded]
public class HomeController : ApiController
{
private readonly IRepository cacheRepo;
public CacheRepository(IRepository cacheRepo)
{
this.cacheRepo= cacheRepo;
}
public IEnumerable<SomeObject> Get()
{
return this.cacheRepo.Get();
}
}
正如您所看到的,我已经重新使用该接口在数据存储库上添加缓存层,这种模式运行得非常整齐。然后我使用了一些自定义属性来告诉Ninject我需要某种类型的IRepository。配置如下:
kernel.Bind<IRepository>().To<DbRepository>().WhenClassHas<DataNeeded>();
kernel.Bind<IRepository>().To<CacheRepository>().WhenClassHas<CacheNeeded>();
有没有办法在Autofac中模仿这种行为?
答案 0 :(得分:0)
我无法想到使用Autofac对这种机制进行任何简洁明了的实现,但也许您可以使用Autofac的meanings of selecting implementation之一。我会使用键控服务,在您的情况下看起来像这样:首先,您需要定义枚举
而不是自定义属性enum RepositoryKind {CacheNeeded, DataNeeded}
然后注册使用提供缓存或数据功能的组件标记它们的组件,例如:
builder.RegisterType<DbRepository>()
.Keyed<IRepository>(RepositoryKind.CacheNeeded);
builder.Register(c => new CacheRepository(c.ResolveKeyed<IRepository(RepositoryKind.CacheNeeded)))
.Keyed<IRepository>(RepositoryKind.DataNeeded);
builder.Register(c => new HomeController(c.ResolveKeyed<IRepository>(RepositoryKind.DataNeeded)));
这种方法的优点是您不会在控制器中显示您的实现细节并在配置中应用缓存。