使用RegisterAssemblyTypes时如何使用Autofac注册装饰器?

问题描述:

这是我的代码使用RegisterAssemblyTypes时如何使用Autofac注册装饰器?

public interface ICommandHandler<T> 
{ 
    void Handle(T command); 
} 

public class CreateUserCommandHandler : ICommandHandler<CreateUserCommand> 
{ 
    public void Handle(CreateUserCommand command) 
    { 
     // do something with the command 
    } 
} 

public class LoggingCommandDecorator<TCommand> : ICommandHandler<TCommand> 
{ 
    private readonly ICommandHandler<TCommand> _commandHandler; 

    public LoggingCommandDecorator(ICommandHandler<TCommand> commandHandler) 
    { 
     _commandHandler = commandHandler; 
    } 

    public void Handle(TCommand command) 
    { 
     Debug.WriteLine("Logging..."); 

     _commandHandler.Handle(command); 
    } 
} 

这里是我的注册:

private void SetupAutofac() 
{ 
    var builder = new ContainerBuilder(); 

    // Register your MVC controllers. 
    builder.RegisterControllers(typeof(WebApiApplication).Assembly); 

    // OPTIONAL: Register model binders that require DI. 
    builder.RegisterModelBinders(Assembly.GetExecutingAssembly()); 
    builder.RegisterModelBinderProvider(); 

    var assemblies = AppDomain.CurrentDomain.GetAssemblies(); 
    builder.RegisterAssemblyTypes(assemblies) 
      .As(o => o.GetInterfaces() 
      .Where(i => i.IsClosedTypeOf(typeof(ICommandHandler<>))) 
      .Select(i => new KeyedService("Handler", i))); 

    builder.RegisterGenericDecorator(typeof(LoggingCommandDecorator<>), 
          typeof(ICommandHandler<>), 
          "Handler", "DecoratedHandler"); 


    var container = builder.Build(); 

    DependencyResolver.SetResolver(new AutofacDependencyResolver(container)); 
} 

当我运行这段代码,我得到以下异常:

建设者没有发现 可以使用0123调用'Autofac.Core.Activators.Reflection.DefaultConstructorFinder'类型 'AspectDemo.Controllers.HomeController'可用服务和参数:无法解析参数 'AspectDemo.Business.ICommandHandler 1[AspectDemo.Business.Users.CreateUserCommand] createUserHandler' of constructor 'Void .ctor(AspectDemo.Business.ICommandHandler 1 [AspectDemo.Business.Users.CreateUserCommand])'。

当我使用以下作为我的注册,我没有得到异常,但我也没有任何装饰。

builder.RegisterAssemblyTypes(assemblies) 
     .AsClosedTypesOf(typeof(ICommandHandler<>)) 
     .AsImplementedInterfaces(); 

我该怎么做才能使用装饰器?

注:现在我只是使用一个装饰器,但最终我认为我有大约4-5个装饰器。

+0

拆卸装饰所有的MVC逻辑,使用你的确切语法,我可以让装饰器按预期工作。指出你的问题可能在其他地方?!你能否看到如果你可以去掉所有的MVC逻辑并发布你仍然无法使装饰器工作的代码? – Ruskin

当您使用RegisterGenericDecorator方法的toKey参数,它导致了一个名为注册,所以你必须要解决的一个名为ICommandHandler

builder.RegisterGenericDecorator(
    typeof(LoggingCommandDecorator<>), 
    typeof(ICommandHandler<>), 
    fromKey : "Handler", 
    toKey : "DecoratedHandler"); 

然后你就可以解决这个问题是这样的:

container.ResolveKeyed<ICommandHandler<CreateUserCommand>>("DecoratedHandler"); 

toKey参数是可选的:

builder.RegisterGenericDecorator(
    typeof(LoggingCommandDecorator<>), 
    typeof(ICommandHandler<>), 
    fromKey : "Handler"); 

然后你就可以解决这个问题是这样的:

container.Resolve<ICommandHandler<CreateUserCommand>>(); 

toKey是有用的,当你有中间装饰:

builder.RegisterGenericDecorator(
    typeof(LoggingCommandDecorator<>), 
    typeof(ICommandHandler<>), 
    fromKey : "Original", 
    toKey : "Logging"); 

builder.RegisterGenericDecorator(
    typeof(AuthorizationCommandDecorator<>), 
    typeof(ICommandHandler<>), 
    fromKey : "Logging"); 

在这种情况下,ICommandHandler<CreateUserCommand>LoggingCommandDecorator<>AuthorizationCommandDecorator<>

+0

我提供了'toKey'参数和“DecoratedHandler”。当我离开这个时,everyhting工作。谢谢。 – Martijn