Autofac 注册嵌套类型?

Autofac register nested type?

假设我有这四种类型(带有构造函数)。

public class MyDbContext : IDataContextAsync
{
    public class MyDataContext() { }
}

public class UnitOfWork : IUnitOfWorkAsync
{
    public UnitOfWork(IDataContextAsync dataContext)
    {
        _dataContext = dataContext;
    }
}

public class Repository<TEntity> : IRepositoryAsync<TEntity>
{
    public Repository(IDataContextAsync context, IUnitOfWorkAsync unitOfWork)
    { 
        _context = context;
        _unitOfWork = unitOfWork;
    } 
}

public class AccountService : IAccountService
{
    private readonly IUnitOfWorkAsync _uow;
    private readonly IRepositoryAsync<Account> _repository;

    public AccountService(IUnitOfWorkAsync uow, IRepositoryAsync<Account> repository)
    {
        _uow = uow;
        _repository = repository;
    }
}

我尝试像这样在我的容器中注册它们(顺便说一句,我正在使用 WCF)。

var builder = new ContainerBuilder();
builder.RegisterType<MyDbContext>().As<IDataContextAsync>();
builder.RegisterType<UnitOfWork>().As<IUnitOfWorkAsync>();
builder.RegisterGeneric(typeof(Repository<>)).As(typeof(IRepositoryAsync<>));

builder.RegisterAssemblyTypes(typeof(AccountService).Assembly)
    .Where(t => t.Name.EndsWith("Service"))
    .As(t => t.GetInterfaces().FirstOrDefault(
        i => i.Name == "I" + t.Name));

Container = builder.Build();

注入到 AccountService 的容器生成的 unitOfWork 实例似乎与容器实例化存储库时创建的 unitOfWork 实例不同。如何确保使用相同的实例实例化存储库?例如,这是在没有容器的情况下通常如何实例化对象的方式。

var context = new MyDbContext();
_uow = new UnitOfWork(context);
_repository = new Repository<Account>(context, _uow);

AccountService service = new AccountService(_uow, _repository);

如您所见,_uow 和用于创建存储库的 _uow 参数是同一个实例。当 Autofac 实例化对象时情况并非如此,我似乎无法弄清楚如何 "tie them together".

默认情况下 Autofac 范围是每个依赖项。这意味着每次 Autofac 需要解析依赖项时,它都会 return 一个新实例。

如果您希望每个生命周期或请求都有一个通用实例,则必须使用适当的范围注册您的类型。

var builder = new ContainerBuilder();
builder.RegisterType<MyDbContext>()
       .As<IDataContextAsync>()
       .InstancePerLifetimeScope();
builder.RegisterType<UnitOfWork>()
       .As<IUnitOfWorkAsync>()
       .InstancePerLifetimeScope();
builder.RegisterGeneric(typeof(Repository<>))
       .As(typeof(IRepositoryAsync<>))
       .InstancePerLifetimeScope();

builder.RegisterAssemblyTypes(typeof(AccountService).Assembly)
       .Where(t => t.Name.EndsWith("Service"))
       .As(t => t.GetInterfaces().FirstOrDefault(i => i.Name == "I" + t.Name))
       .InstancePerLifetimeScope();

Container = builder.Build();

有关详细信息,请参阅 Autofac 文档中的 Instance Scope

顺便说一句,AutofacWCF 的集成似乎不支持每个请求的生命周期

Due to WCF internals, there is no explicit support in WCF for per-request lifetime dependencies.

http://docs.autofac.org/en/latest/integration/wcf.html

此限制与 WCF 具有自己的实例范围这一事实有关。建议使用 InstanceContextMode.PerCall 以确保 WCF 为每个 WCF 调用请求一个新的服务实例。您可以使用 ServiceBehavior 属性

[ServiceBehavior(InstanceContextMode = InstanceContextMode.PerCall)]
public class MyService : IMyService
{ }

我阅读了 AutofacInstanceContext.cs 的源代码,似乎为每个 WCF 调用创建了一个新的 LifetimeScope。因此,您可以将依赖项注册为 InstancePerLifetimeScope,它应该可以工作。