如何使用Autofac在一个构造函数中注入类的装饰器而在另一个构造函数中注入类本身?

时间:2015-06-18 22:04:04

标签: c# dependency-injection decorator autofac

我有一个IoCConfig在RegisterDependencies方法中首先注册所有Services(与ServiceBase相同的程序集),除了一个服务和一个名为LastActivityUpdator的类,这个名为AnonymousUserLastActivityUpdator的类的装饰器,它们都实现了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 - &gt;
Services.AnonymousUserService - &gt;
Services.AnonymousUserLastActivityUpdator - &gt;
Services.AnonymousUserLastActivityUpdator - &gt; System.Object - &gt;
Services.AnonymousUserLastActivityUpdator

我调整了代码的一些Cyril的答案(修复了一些拼写错误并切换了匿名和普通的UserService)我可能犯了一个错误,这里是:

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

1 个答案:

答案 0 :(得分:1)

UserServiceAnonymousUserService有两种注册方式。

在第一个解决方案中,您通过显式调用构造函数并通过询问 Autofac 来解析AnonymousUserService来注册AnonymousUserLastActivityUpdator,但此服务没有注册。您可以解析名为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 1}}方法

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

您不必同时进行两次注册,最后一次注册就足够了。