如何使用 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();

不幸的是,这不起作用。 AnonymousUserServiceUserService 都获得了 LastActivityUpdator 的实例,而我希望 AnonymousUserService 获得 AnonymousUserService.

的实例

有谁知道为什么我的 RegisterDependencies 方法不提供 LastActivityUpdatorUserService 以及我如何才能做到这一点?

/编辑

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

您有 UserServiceAnonymousUserService 两种注册。

在第一个解决方案中,您通过显式调用构造函数并要求 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();

您不必同时注册,最后一个应该足以满足您的场景。