如何使用 Autofac 在一个构造函数中注入 class 的装饰器,而在另一个构造函数中注入 class 本身?
How to use Autofac to inject decorator of a class in one constructor and the class itself in another?
我有一个 IoCConfig
,其中在 RegisterDependencies 方法中首先注册了所有 Services
(与 ServiceBase
相同的程序集),除了一个服务和一个 class 调用LastActivityUpdator
和这个 class 的装饰器 AnonymousUserLastActivityUpdator
都实现了 ILastActivityUpdator
.
我想要完成的目标是正确注册装饰器,它已经在 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 . To be complete (I don't think it is relevant to this problem), I am using a keyed service following this answer 之后工作,以决定在其他时间注入哪个 class。
不幸的是,当我结合这些想法时,我总是看到注入了 AnonymousUserLastActivityUpdator
,在 UserService
的情况下也是如此,我希望提供 LastActivityUpdator
。
在下面找到 IocConfig
,它既使用了注册装饰器的想法,又提供了一种类型的特定 classes:
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 方法不提供 LastActivityUpdator
到 UserService
以及我如何才能做到这一点?
/编辑
使用 Cyril 的回答和一些调整,注册适用于 UserService
,但是一旦用户注销并使用 AnonymousUserService
,我就会收到错误消息:
Circular component dependency detected:
Services.AnonymousUserService ->
Services.AnonymousUserService ->
Services.AnonymousUserLastActivityUpdator ->
Services.AnonymousUserLastActivityUpdator -> System.Object ->
Services.AnonymousUserLastActivityUpdator
我稍微调整了 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));
您有 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();
您不必同时注册,最后一个应该足以满足您的场景。
我有一个 IoCConfig
,其中在 RegisterDependencies 方法中首先注册了所有 Services
(与 ServiceBase
相同的程序集),除了一个服务和一个 class 调用LastActivityUpdator
和这个 class 的装饰器 AnonymousUserLastActivityUpdator
都实现了 ILastActivityUpdator
.
我想要完成的目标是正确注册装饰器,它已经在 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
不幸的是,当我结合这些想法时,我总是看到注入了 AnonymousUserLastActivityUpdator
,在 UserService
的情况下也是如此,我希望提供 LastActivityUpdator
。
在下面找到 IocConfig
,它既使用了注册装饰器的想法,又提供了一种类型的特定 classes:
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 方法不提供 LastActivityUpdator
到 UserService
以及我如何才能做到这一点?
/编辑
使用 Cyril 的回答和一些调整,注册适用于 UserService
,但是一旦用户注销并使用 AnonymousUserService
,我就会收到错误消息:
Circular component dependency detected:
Services.AnonymousUserService ->
Services.AnonymousUserService ->
Services.AnonymousUserLastActivityUpdator ->
Services.AnonymousUserLastActivityUpdator -> System.Object ->
Services.AnonymousUserLastActivityUpdator
我稍微调整了 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));
您有 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();
您不必同时注册,最后一个应该足以满足您的场景。