如何使用 Autofac 在一个构造函数中注入类的装饰器,在另一个构造函数中注入类本身
本文关键字:注入 构造函数 另一个 何使用 一个 Autofac | 更新日期: 2023-09-27 17:57:06
我有一个IoCConfig
,在 RegisterDependencies 方法中,首先注册所有Services
(与ServiceBase
相同的程序集),除了一个名为 LastActivityUpdator
的服务和一个类以及一个名为 AnonymousUserLastActivityUpdator
的此类装饰器,它们都实现了 ILastActivityUpdator
。
我想要实现的目标是正确注册装饰器,它已经在这个答案之后工作了。我还要求一种方法,让一个类(UserService
)使用LastActivityUpdator
,而另一个类(AnonymousUserService
)使用AnonymousUserLastActivityUpdator
,这在这里得到了回答。为了完整(我认为这与这个问题无关),我正在使用此答案的键控服务来决定在其他时间注入哪个类。
不幸的是,当我结合这些想法时,我总是看到注入AnonymousUserLastActivityUpdator
,在我希望提供LastActivityUpdator
的UserService
的情况下也是如此。
在下面找到IocConfig
,它既使用想法来注册装饰器,又使用一种类型提供特定类:
builder.RegisterAssemblyTypes(typeof(ServiceBase).Assembly)
.Except<AnonymousUserService>()
.Except<LastActivityUpdator>()
.Except<AnonymousUserLastActivityUpdator>()
.AsImplementedInterfaces()
.InstancePerRequest();
builder.RegisterType<LastActivityUpdator>()
.Named<ILastActivityUpdator>("lastActivityUpdator");
builder.RegisterType<AnonymousUserLastActivityUpdator>()
.Named<ILastActivityUpdator>("anonymousUserLastActivityUpdator");
builder.RegisterDecorator<ILastActivityUpdator>(
(c, inner) => c.ResolveNamed<ILastActivityUpdator>("anonymousUserLastActivityUpdator",
TypedParameter.From(inner)),
fromKey: "lastActivityUpdator")
.As<ILastActivityUpdator>();
builder.Register(c => new UserService(
c.Resolve<OogstplannerUnitOfWork>(),
c.Resolve<CookieProvider>(),
c.Resolve<ILastActivityUpdator>()));
builder.Register(c => new AnonymousUserService(
c.Resolve<OogstplannerUnitOfWork>(),
c.Resolve<CookieProvider>(),
c.Resolve<AnonymousUserLastActivityUpdator>()));
builder.RegisterType<AnonymousUserService>()
.Keyed<IUserService>(AuthenticatedStatus.Anonymous)
.InstancePerRequest();
builder.RegisterType<UserService>()
.Keyed<IUserService>(AuthenticatedStatus.Authenticated)
.InstancePerRequest();
不幸的是,这不起作用。AnonymousUserService
和UserService
都得到LastActivityUpdator
的实例,而我希望AnonymousUserService
得到AnonymousUserService
的实例。
有谁知道为什么我的 RegisterDependencies 方法不提供UserService
LastActivityUpdator
以及如何完成此操作?
/编辑
使用 Cyril 的答案和一些调整,注册适用于UserService
,但是一旦用户注销并使用AnonymousUserService
,我就会收到错误:
检测到循环组件依赖关系:
服务.匿名用户服务 -> 服务.匿名用户服务 -> 服务.匿名用户最后活动更新器 -> 服务.匿名用户最后活动更新器 -> 系统.对象 ->
服务.匿名用户最后活动更新器
我稍微调整了 Cyril 答案的代码(修复了一些拼写错误并切换了匿名和普通用户服务),我可能犯了一个错误,这里是:
builder.RegisterAssemblyTypes(typeof(ServiceBase).Assembly)
.Except<AnonymousUserService>()
.Except<LastActivityUpdator>()
.Except<AnonymousUserLastActivityUpdator>()
.AsImplementedInterfaces()
.InstancePerRequest();
builder.RegisterType<LastActivityUpdator>()
.Named<ILastActivityUpdator>("lastActivityUpdator");
builder.RegisterType<AnonymousUserLastActivityUpdator>()
.Named<ILastActivityUpdator>("anonymousUserLastActivityUpdator");
builder.RegisterDecorator<ILastActivityUpdator>(
(c, inner) => c.ResolveNamed<ILastActivityUpdator>("anonymousUserLastActivityUpdator",
TypedParameter.From(inner)),
fromKey: "lastActivityUpdator")
.As<ILastActivityUpdator>();
builder.RegisterType<UserService>()
.Keyed<IUserService>(AuthenticatedStatus.Authenticated)
.WithParameter(
(p, c) => p.Name == "lastActivityUpdator",
(p, c) => c.ResolveNamed<ILastActivityUpdator>("lastActivityUpdator"))
.InstancePerRequest();
builder.RegisterType<AnonymousUserService>()
.Keyed<IUserService>(AuthenticatedStatus.Anonymous)
.WithParameter(
(p, c) => p.Name == "anonymousUserLastActivityUpdator",
(p, c) => c.ResolveNamed<ILastActivityUpdator>("anonymousUserLastActivityUpdator"))
.InstancePerRequest();
var container = builder.Build();
DependencyResolver.SetResolver(new AutofacDependencyResolver(container));
您有 2 种UserService
和AnonymousUserService
注册。
在第一个解决方案中,通过显式调用构造函数并要求 Autofac 解析AnonymousUserLastActivityUpdator
来注册AnonymousUserService
,但没有注册此服务。您可以解析命名ILastActivityUpdator
,而不是解析此类型
builder.Register(c => new UserService(
c.Resolve<OogstplannerUnitOfWork>(),
c.Resolve<CookieProvider>(),
c.Resolve<ILastActivityUpdator>()));
builder.Register(c => new AnonymousUserService(
c.Resolve<OogstplannerUnitOfWork>(),
c.Resolve<CookieProvider>(),
c.ResolveNamed<ILastActivityUpdator>("anonymousUserLastActivityUpdator")));
第二个注册是Keyed
但你没有指定AnonymousUserService
应使用anonymousUserLastActivityUpdater
你可以使用 WithParameter
方法执行此操作
builder.RegisterType<AnonymousUserService>()
.Keyed<IUserService>(AuthenticatedStatus.Authenticated)
.InstancePerRequest();
builder.RegisterType<UserService>()
.Keyed<IUserService>(AuthenticatedStatus.Anonymous)
.WithParameter(
(pi, c) => pi.Name == "updater",
(pi, c) => ResolveNamed<ILastActivityUpdator>("anonymousUserLastActivityUpdator"))
.InstancePerRequest();
不必同时进行两次注册,最后一个注册应该足以满足你的方案。