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

时间:2016-01-20 17:09:28

标签: c# decorator 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));
}

当我运行此代码时,我得到以下异常:

  

没有找到的构造函数   &#39; Autofac.Core.Activators.Reflection.DefaultConstructorFinder&#39;在类型上   &#39; AspectDemo.Controllers.HomeController&#39;可以用。调用   可用的服务和参数:无法解析参数   &#39; {AspectDemo.Business.ICommandHandler {1}} 1 [AspectDemo.Business.Users.CreateUserCommand])&#39;

当我使用以下作为我的注册时,我没有得到例外,但我也没有任何装饰者。

1[AspectDemo.Business.Users.CreateUserCommand]
  createUserHandler' of constructor 'Void
  .ctor(AspectDemo.Business.ICommandHandler

我需要做什么才能使用装饰器?

注意:现在我只使用一个装饰器,但最后我觉得我有大约4-5个装饰器。

1 个答案:

答案 0 :(得分:1)

当您使用toKey方法的RegisterGenericDecorator参数时,会导致命名注册,因此您必须解析名为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<>装饰