【问题标题】:How to use Autofac to inject decorator of a class in one constructor and the class itself in another?如何使用 Autofac 在一个构造函数中注入类的装饰器,在另一个构造函数中注入类本身?
【发布时间】:2015-09-04 18:06:52
【问题描述】:

我有一个IoCConfig,其中首先在 RegisterDependencies 方法中注册所有Services(与ServiceBase 相同的程序集),除了一个服务和一个名为LastActivityUpdator 的类和一个名为@987654328 的类的装饰器@ 两者都实现了ILastActivityUpdator

我想要完成的目标是正确注册装饰器,这已经在this answer 之后工作。我还要求一种方法让一个班级(UserService)使用LastActivityUpdator,而另一个(AnonymousUserService)使用AnonymousUserLastActivityUpdator,得到了here的回答。为了完整起见(我认为这与这个问题无关),我使用this answer 之后的键控服务来决定在其他时间注入哪个类。

不幸的是,当我结合这些想法时,我总是看到注入了 AnonymousUserLastActivityUpdator,同样在 UserService 的情况下,我希望提供 LastActivityUpdator

在您下方找到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();

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

有谁知道为什么我的 RegisterDependencies 方法没有提供 LastActivityUpdatorUserService 以及我该如何实现这一点?

/编辑

使用 Cyril 的答案和一些调整,注册适用于 UserService,但是一旦用户注销并使用 AnonymousUserService,我就会收到错误:

检测到循环组件依赖:
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));

【问题讨论】:

    标签: c# dependency-injection decorator autofac


    【解决方案1】:

    您有两种注册 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();
    

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

    【讨论】:

    • 嗨西里尔,再次感谢您的回答。我们越来越近了:UserService 注入了LastActivityUpdator,但是一旦需要AnonymousUserService,就会弹出错误Circular component dependency detected。我确实对您提供的答案进行了一些调整,所以我可能在那里犯了错误。我已经更新了答案(在 /edit 下),如果你能看一看会很高兴
    • 您不应该同时使用WithParameter 方法进行注册。通过这样做,您的注册都没有使用装饰器。对于该错误,您是否需要使用 RegisterAssemblyTypes 方法注册您的类型?我建议您手动注册所有类型,并且不要使用汇编扫描之类的东西。它将让您完全控制您的注册。尝试手动注册您的类型,错误消息可能更明确
    • 谢谢!我让它工作了!工作注册注册UserService如下:builder.Register(c =&gt; new UserService( c.Resolve&lt;IOogstplannerUnitOfWork&gt;(), c.Resolve&lt;ICookieProvider&gt;(), c.ResolveNamed&lt;ILastActivityUpdator&gt;("lastActivityUpdator"))) .As&lt;IUserService&gt;() .InstancePerRequest();。我认为问题在于,解析ILastActivityUpdator 自动给出了AnonymousUserLastActivityUpdator,这不会发生在 ResolveNamed 方法中。再次感谢您的帮助!
    • 另外,(p, c) =&gt; p.Name == "updater" 部分不能是(p, c) =&gt; p.Name == "anonymousUserLastActivityUpdator",因为当使用与命名注册相同的名称时,您会得到一个DependencyResolutionException
    猜你喜欢
    • 2017-02-25
    • 2011-11-04
    • 1970-01-01
    • 2015-08-05
    • 1970-01-01
    • 2020-05-20
    • 1970-01-01
    • 2014-08-01
    • 1970-01-01
    相关资源
    最近更新 更多