3

我有一个存储库接口和类。我还有服务接口和类,它们依赖于存储库接口。典型的 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>();
    }
}

我在温莎城堡做到了这一点。我刚刚添加了课程,它立即生效,没有任何注册更改。这对我来说真是太棒了!:) 现在我尝试对 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();

在此之后将为每个缓存的存储库进行注册。

4

2 回答 2

1

看起来你有一个装饰器,而不是循环依赖。我将假设主要实现被称为CustomerRepository. 最简单的注册方法是

var cb = new ContainerBuilder();

cb.RegisterType<CustomerRepository>().AsSelf();

cb.Register(c => new CachedCustomerRepository(c.Resolve<CustomerRepository>()))
    .As<ICustomerRepository>();

这通过将主要实现注册为自身,然后将装饰器注册为ICustomerRepository. 因此,当 Autofac 需要解析 anICustomerRepository时,它将提供装饰器。

编辑

现在我看到了您的注册码,如果您想避免在合成根目录中进行手动工作,我可以建议您这样做。(当然,如果你的 repos 少于 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));
于 2013-09-18T01:45:31.127 回答
1

Autofac 网站上有一个 wiki 页面,解释了如何注册循环依赖以及支持哪些类型的关系。您很可能需要将系统中的依赖项之一切换为属性依赖项而不是构造函数参数 - 不支持构造函数/构造函数依赖项。

于 2013-09-17T20:40:20.500 回答