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 集成,如下所述。
无服务服务
如果您想在没有 .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
假设我像这样手动实例化我的对象:
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 集成,如下所述。
无服务服务
如果您想在没有 .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