我有一个存储库接口(interface)和类。我还有服务接口(interface)和类,它们依赖于存储库接口(interface)。典型的DI。我的目标是在服务和存储库之间添加缓存,而不是触及服务或存储库。这是代码:
public class CachedCustomerRepository : ICustomerRepository
{
private readonly ICustomerRepository _repository;
private readonly ConcurrentDictionary<int, Customer> _cache;
public CachedCustomerRepository(ICustomerRepository repository)
{
if (repository == null)
throw new ArgumentNullException("repository");
this._repository = repository;
this._cache = new ConcurrentDictionary<int, Customer>();
}
}
我已经在温莎城堡做到了这一点。我刚刚添加了该类(class),它立即生效,没有任何注册更改。这对我来说真是哇的效果! :) 现在我尝试用 Autofac 做同样的事情,但失败了。它提示循环依赖,但我不知道如何注册它。
编辑 - 这是注册:
builder.RegisterAssemblyTypes(typeof(ICustomerRepository).Assembly)
.Where(t => t.Name.EndsWith("Repository"))
.AsImplementedInterfaces()
.SingleInstance();
编辑 - 现在注册:
builder.RegisterAssemblyTypes(typeof(ICustomerRepository).Assembly)
.Where(t => t.Name.EndsWith("Repository") && !t.Name.StartsWith("Cached"))
.AsImplementedInterfaces()
.SingleInstance();
此后,将注册每个缓存的存储库。
最佳答案
看起来你有一个装饰器,而不是循环依赖。我假设主要实现称为 CustomerRepository
。注册的最简单方法是
var cb = new ContainerBuilder();
cb.RegisterType<CustomerRepository>().AsSelf();
cb.Register(c => new CachedCustomerRepository(c.Resolve<CustomerRepository>()))
.As<ICustomerRepository>();
这是通过将主实现注册为其本身,然后将装饰器注册为 ICustomerRepository
来实现的。因此,当 Autofac 需要解析 ICustomerRepository
时,它将提供装饰器。
编辑
既然我看到了您的注册码,如果您想避免在组合根目录中进行手动工作,我可以建议您这样做。 (当然,如果你的存储库少于 10 个,我可能会使用更简单、更手动的版本)
var cb = new ContainerBuilder();
foreach (var type in this.GetType().Assembly.GetTypes()
.Where(t => t.IsClass && !t.IsAbstract))
{
var iRepoType = type.GetInterfaces()
.SingleOrDefault(i => i.Name.EndsWith("Repository"));
if (iRepoType == null)
{
continue;
}
bool isRepo = type.Name.EndsWith("Repository");
bool isCache = type.Name.StartsWith("Cache");
if (isRepo && !isCache)
{
cb.RegisterType(type)
.Named("mainImpl", iRepoType)
.SingleInstance();
}
else if (isRepo && isCache)
{
cb.RegisterType(type).WithParameter(
(prop, context) => prop.ParameterType == iRepoType,
(prop, context) => context.ResolveNamed("mainImpl", iRepoType))
.As(iRepoType)
.SingleInstance();
}
}
var container = cb.Build();
var repo = container.Resolve<ICustomerRepository>();
Assert.IsInstanceOfType(repo, typeof(CachedCustomerRepository));
var cast = (CachedCustomerRepository)repo;
Assert.IsInstanceOfType(cast.wrapped, typeof(CustomerRepository));
关于autofac - 如何在Autofac中注册循环类型?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/18848677/