如何使用Autofac在一个构造函数中注入一个类的装饰器,并在另一个构造函数中注入该类本身? [英] How to use Autofac to inject decorator of a class in one constructor and the class itself in another?
问题描述
我有一个IoCConfig
,其中首先在RegisterDependencies方法中注册所有Services
(与ServiceBase
相同的程序集),除了一项服务和一个称为LastActivityUpdator
的类以及该类称为ILastActivityUpdator
.
I have an IoCConfig
where in the RegisterDependencies method first all Services
(same assembly as ServiceBase
) are registered, except for one service and one class called LastActivityUpdator
and a decorator of this class called AnonymousUserLastActivityUpdator
which both implement ILastActivityUpdator
.
我要完成的目标是正确注册装饰器,该装饰器在此处.为完整起见(我认为这与该问题无关),我正在使用
The goals I want to accomplish is to have the decorator registered properly, which already works following this answer. And I also asked for a way to for one class (UserService
) use the LastActivityUpdator
and for another (AnonymousUserService
) use the AnonymousUserLastActivityUpdator
, which was answered here. To be complete (I don't think it is relevant to this problem), I am using a keyed service following this answer to decide which class is injected in other times.
不幸的是,当我结合这些想法时,总是看到注入AnonymousUserLastActivityUpdator
的情况,在UserService
的情况下,我也希望提供LastActivityUpdator
.
Unfortunately, when I combine the ideas I always see an AnonymousUserLastActivityUpdator
injected, also in the case of UserService
where I want a LastActivityUpdator
to be provided.
在您下面"找到IocConfig
,它使用了这种思想来注册装饰器并提供一种类型的特定类:
Below you'' find the IocConfig
which uses both the idea to register the decorator and to provide specific classes with one type:
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
的实例.
Unfortunately this does not work. Both the AnonymousUserService
and the UserService
get an instance of the LastActivityUpdator
, while I want AnonymousUserService
to get an instance of the AnonymousUserService
.
有人知道为什么我的RegisterDependencies方法不提供LastActivityUpdator
到UserService
的原因,以及我如何做到这一点?
Does anyone know why my RegisterDependencies method does not provide the LastActivityUpdator
to UserService
and how I can accomplish this?
/编辑
使用Cyril的答案和一些调整,UserService
的注册有效,但是一旦用户注销并使用了AnonymousUserService
,我就会收到错误消息:
Using the answer of Cyril and some adjustments the registering works for the UserService
, but once the user logs out and a AnonymousUserService
is used I get the error:
检测到圆形组件依赖项:
Services.AnonymousUserService->
Services.AnonymousUserService->
Services.AnonymousUserLastActivityUpdator->
Services.AnonymousUserLastActivityUpdator-> System.Object->
Services. AnonymousUserLastActivityUpdator
Circular component dependency detected:
Services.AnonymousUserService ->
Services.AnonymousUserService ->
Services.AnonymousUserLastActivityUpdator ->
Services.AnonymousUserLastActivityUpdator -> System.Object ->
Services.AnonymousUserLastActivityUpdator
我对Cyril的答案的代码进行了一些调整(修正了一些拼写错误,并切换了匿名用户服务和普通UserService),我可能会犯一个错误,这里是:
I adjusted the code somewhat of Cyril's answer (fixed some typos and switched the anonymous- and normal UserService) and I might have made a mistake, here it is:
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));
推荐答案
您有UserService
和AnonymousUserService
两种注册.
在第一个解决方案中,您通过显式调用构造函数并要求 Autofac 解析AnonymousUserLastActivityUpdator
来注册AnonymousUserService
,但该服务没有注册.除了解决这种类型,您还可以解决命名为ILastActivityUpdator
In the first solution you register AnonymousUserService
by explicitly calling the constructor and by asking Autofac to resolve a AnonymousUserLastActivityUpdator
but there is no registration for this service. Instead of resolving this type, you can resolve a named 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
方法
The second registration is a Keyed
but you don't specify that the AnonymousUserService
should use a anonymousUserLastActivityUpdater
you could do it by using the WithParameter
method
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();
您不必同时注册两个,最后一个注册对于您的情况就足够了.
You don't have to have both registration, the last one should be enough for your scenario.
这篇关于如何使用Autofac在一个构造函数中注入一个类的装饰器,并在另一个构造函数中注入该类本身?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!