如何使用Autofac在一个构造函数中注入一个类的装饰器,并在另一个构造函数中注入该类本身? [英] How to use Autofac to inject decorator of a class in one constructor and the class itself in another?

查看:69
本文介绍了如何使用Autofac在一个构造函数中注入一个类的装饰器,并在另一个构造函数中注入该类本身?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个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();

不幸的是,这不起作用. AnonymousUserServiceUserService都获取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方法不提供LastActivityUpdatorUserService的原因,以及我如何做到这一点?

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

推荐答案

您有UserServiceAnonymousUserService两种注册.

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

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆