Autofac 实例管理?

Autofac instance management?

假设我像这样手动实例化我的对象:

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

相反,我想注入它们并像这样注册它们:

private readonly IUnitOfWorkAsync _uow;
private readonly IRepositoryAsync<Account> _repository;

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

这里是注册。

builder.RegisterType<MyDbContext>().As<IDataContextAsync>().InstancePerDependency();
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));

我的服务已发布到 IIS,看起来不错,但无法正常运行。例如,我去插入一个新帐户,但它没有保存到数据库中,也没有出错。似乎注入的 UnitOfWork 与用于实例化存储库的 UnitOfWork 不同。我用一些代码证实了这一点 像这样的构造函数:

if(_uow.GetHashCode() != _repository.MyUow.GetHashCode())
    throw new ArgumentException("Bad UOW");

如果我注入 UnitOfWork 和存储库,则会出现异常。如果我手动实例化我的对象,我不会得到异常。我已经尝试将我的注册更改为 .InstancePerOwned() 以获取服务和其他各种注册更改,但均无济于事。如何使用 Autofac 注册基于它已经实例化的 UnitOfWork 正确实例化我的存储库?我认为默认的 .InstancePerDependency() 就足够了,但事实并非如此。谢谢。


编辑 1: 我正在使用 WCF,这是我的 CustomHostFactory。我看不到文档中所述的指定 .InstancePerRequest() 的选项。另外,有趣的是,这一行在下面的代码中并不重要。如果我把它拿出来,一切都完全一样。 AutofacServiceHostFactory.Container = 容器;

protected override ServiceHost CreateServiceHost(Type serviceType, Uri[] baseAddresses)
{
    Type contractType = GetContractType(serviceType);

    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));

    var container = builder.Build();
    AutofacServiceHostFactory.Container = container;
    var host = new CustomServiceHost(serviceType, baseAddresses);
    host.AddDependencyInjectionBehavior(contractType, container);

    return host;
}
private static Type GetContractType(Type serviceType)
{
    return serviceType.GetInterfaces()
        .FirstOrDefault(i => Attribute.IsDefined(i, typeof(ServiceContractAttribute), false));
}

InstancePerRequest 仅适用于 WebForms 和 MVC 集成包。

尝试在 svc.less 模式下正确使用 Autofac 与 WCF 集成,如下所述。

From Autofac docs:

无服务服务

如果您想在没有 .svc 文件的情况下使用服务,Autofac 可以使用该文件。

如上所示,向容器注册您的服务。

var builder = new ContainerBuilder();
builder.RegisterType<Service1>();
AutofacHostFactory.Container = builder.Build();

要使用无 svc 服务,请在 web.config 文件中的 serviceActivation 元素下添加一个工厂条目。这确保了 AutofacServiceHostFactory 用于激活服务。

<serviceHostingEnvironment aspNetCompatibilityEnabled="true" multipleSiteBindingsEnabled="true">
  <serviceActivations>
    <add factory="Autofac.Integration.Wcf.AutofacServiceHostFactory"
         relativeAddress="~/Service1.svc"
         service="TestService.Service1" />
  </serviceActivations>
</serviceHostingEnvironment>

我需要像这样更改注册:

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();

AutofacHostFactory.Container = builder.Build();

以及使用以下服务行为属性将我的每项服务设置为按调用运行:

InstanceContextMode = InstanceContextMode.PerCall