tra*_*max 5 c# decorator autofac
我们有许多通用命令处理程序,由Autofac以开放式通用方式注册.我们有几个装饰器来装饰所有手柄.现在我需要为一个命令处理程序注册一个装饰器,而不是影响所有其他命令处理程序.这是我的尝试,但我似乎没有正确注册.
这是与我们的代码类似的简单测试代码:
我们有数百个命令如下:
class NormalCommand : ICommand { }
// This command handler should not be decorated
class NormalCommandHandler : ICommandHandler<NormalCommand>
{
public void Handle(NormalCommand command) { }
}
Run Code Online (Sandbox Code Playgroud)
而且我想TestCommandHandler在装饰器中包装TestCommandHandlerDecorator
class TestCommand : ICommand { }
// And I would like to put decorator around this handler
class TestCommandHandler : ICommandHandler<TestCommand>
{
public void Handle(TestCommand command) { }
}
// This decorator should be wrapped only around TestCommandHandler
class TestCommandHandlerDecorator : ICommandHandler<TestCommand>
{
private readonly ICommandHandler<TestCommand> decorated;
public TestCommandHandlerDecorator(ICommandHandler<TestCommand> decorated)
{
this.decorated = decorated;
}
public void Handle(TestCommand command)
{
// do something
decorated.Handle(command);
// do something again
}
}
Run Code Online (Sandbox Code Playgroud)
这就是我注册我的组件的方式:
static class AutofacRegistration
{
public static IContainer RegisterHandlers()
{
var builder = new ContainerBuilder();
//Register All Command Handlers but not decorators
builder.RegisterAssemblyTypes(Assembly.GetAssembly(typeof(AutofacRegistration)))
.Where(t => !t.Name.EndsWith("Decorator"))
.AsClosedTypesOf(typeof(ICommandHandler<>))
.InstancePerLifetimeScope();
// and here is the battle!
builder.RegisterType<TestCommandHandler>()
.Named<ICommandHandler<TestCommand>>("TestHandler")
.InstancePerLifetimeScope();
// this does not seem to wrap the decorator
builder.RegisterDecorator<ICommandHandler<TestCommand>>(
(c, inner) => new TestCommandHandlerDecorator(inner),
fromKey: "TestHandler")
.Named<ICommandHandler<TestCommand>>("TestHandler1")
.InstancePerLifetimeScope();
return builder.Build();
}
}
Run Code Online (Sandbox Code Playgroud)
这就是我尝试确认我得到命令处理程序/装饰器的正确实例的方法:
class AutofacRegistrationTests
{
[Test]
public void ResolveNormalCommand()
{
var container = AutofacRegistration.RegisterHandlers();
var result = container.Resolve<ICommandHandler<NormalCommand>>();
// this resolves correctly
Assert.IsInstanceOf<NormalCommandHandler>(result); // pass
}
[Test]
public void TestCommand_Resolves_AsDecorated()
{
var container = AutofacRegistration.RegisterHandlers();
var result = container.Resolve<ICommandHandler<TestCommand>>();
// and this resolves to TestCommandHandler, not decorated!
Assert.IsInstanceOf<TestCommandHandlerDecorator>(result); // FAILS!
}
}
Run Code Online (Sandbox Code Playgroud)
正如评论所说,装饰器没有被应用,装饰器注册被忽略.
任何想法如何注册这个装饰?我究竟做错了什么?
在用头撞键盘足够多次之后,我对我的问题有了某种解决方案:
static class AutofacRegistration
{
public static IContainer RegisterHandlers()
{
var builder = new ContainerBuilder();
builder.RegisterAssemblyTypes(Assembly.GetAssembly(typeof(AutofacRegistration)))
.AsClosedTypesOf(typeof(ICommandHandler<>))
.InstancePerLifetimeScope();
builder.RegisterType<TestCommandHandler>()
.Named<ICommandHandler<TestCommand>>("TestHandler")
.InstancePerLifetimeScope();
// this works!
builder.Register(c => new TestCommandHandlerDecorator(c.ResolveNamed<ICommandHandler<TestCommand>>("TestHandler")))
.As<ICommandHandler<TestCommand>>()
.InstancePerLifetimeScope();
return builder.Build();
}
}
Run Code Online (Sandbox Code Playgroud)
这里我没有使用 Autofac 的装饰器功能并手动包装装饰器。因此,如果装饰器中的依赖项数量增加,我需要更新容器以解决所有必需的依赖项。
如果您知道更好的解决方案,请告诉我!
| 归档时间: |
|
| 查看次数: |
2010 次 |
| 最近记录: |