我正在尝试使用简单注入器中的一些很好的功能。
我目前在修饰器方面遇到问题,但是当我期待它们时它们也没有被击中。
我正在这样注册:
container.RegisterManyForOpenGeneric(
typeof(ICommandHandler<>),
AppDomain.CurrentDomain.GetAssemblies());
container.RegisterDecorator(
typeof(ICommandHandler<>),
typeof(CreateValidFriendlyUrlCommandHandler<>),
context => context.ServiceType == typeof(ICommandHandler<CreateProductCommand>)
);
container.RegisterDecorator(
typeof(ICommandHandler<>),
typeof(CreateProductValidationCommandHandler<>),
context => context.ServiceType == typeof(ICommandHandler<CreateProductCommand>)
);
我认为我必须遗漏一些内容,因为我希望拨打ICommandHandler<CreateProductCommand>
之前会先调用CreateValidFriendlyUrlCommandHandler<>
和CreateProductValidationCommandHandler<>
。
我尝试了不同的注册:
container.RegisterManyForOpenGeneric(
typeof(ICommandHandler<>),
AppDomain.CurrentDomain.GetAssemblies());
container.RegisterDecorator(
typeof(ICommandHandler<>),
typeof(CreateValidFriendlyUrlCommandHandler<>),
context => context.ImplementationType == typeof(CreateProductCommandHandler)
);
container.RegisterDecorator(
typeof(ICommandHandler<>),
typeof(CreateProductValidationCommandHandler<>),
context => context.ImplementationType == typeof(CreateProductCommandHandler)
);
正如我想在ICommandHandler<CreateProductCommand>
和ICommandHandler<CreateProductCommand>
实施CreateProductValidationCommandHandler
时,CreateValidFriendlyUrlCommandHandler
类型ICommandHandler<CreateProductCommand>
上的CreateProductValidationCommandHandler<TCommand>
注册装扮器可能会发生一些问题参考
但改变那没有区别。
这是我的public class CreateProductValidationCommandHandler<TCommand>
: ICommandHandler<CreateProductCommand>
{
private readonly ICommandHandler<TCommand> decorated;
private readonly IValidationService validationService;
public CreateProductValidationCommandHandler(
ICommandHandler<TCommand> decorated,
IValidationService validationService)
{
this.decorated = decorated;
this.validationService = validationService;
}
public void Handle(CreateProductCommand command)
{
if (!validationService.IsValidFriendlyName(
command.Product.ProductFriendlyUrl))
{
command.ModelStateDictionary.AddModelError(
"ProductFriendlyUrl",
"The Friendly Product Name is not valid...");
return;
}
if (!validationService.IsUniqueFriendlyName(
command.Product.ProductFriendlyUrl))
{
command.ModelStateDictionary.AddModelError(
"ProductFriendlyUrl",
"The Friendly Product Name is ...");
return;
}
}
}
:
CreateValidFriendlyUrlCommandHandler<TCommand>
这是我的public class CreateValidFriendlyUrlCommandHandler<TCommand>
: ICommandHandler<CreateProductCommand>
{
private readonly ICommandHandler<TCommand> decorated;
public CreateValidFriendlyUrlCommandHandler(ICommandHandler<TCommand> decorated)
{
this.decorated = decorated;
}
public void Handle(CreateProductCommand command)
{
if (string.IsNullOrWhiteSpace(
command.Product.ProductFriendlyUrl))
{
command.Product.ProductFriendlyUrl =
MakeFriendlyUrl(command.Product.Name);
}
}
}
:
{{1}}
答案 0 :(得分:3)
问题是Simple Injector永远无法用你的一个装饰器包装ICommandHandler<T>
实现,因为有一个不可解析的泛型类型TCommand
。如果装饰器的Handle
方法调用decorated
实例,您会注意到这一点。例如:
public class CreateValidFriendlyUrlCommandHandler<TCommand>
: ICommandHandler<CreateProductCommand>
{
private readonly ICommandHandler<TCommand> decorated;
public CreateValidFriendlyUrlCommandHandler(
ICommandHandler<TCommand> decorated)
{
this.decorated = decorated;
}
public void Handle(CreateProductCommand command)
{
// This won't compile since CreateProductCommand and
// TCommand are not related.
this.decorated.Handle(command);
}
}
此代码无法编译,因为装饰器的Handle
方法采用CreateProductCommand
参数,而decorated
实例采用TCommand
参数,未指定(并且没有说明CreateProductCommand
是TCommand
)。
实际上你根本没有创建装饰器。装饰器包装它实现的相同接口的实例。在实施ICommandHandler<TCommand>
时包裹ICommandHandler<CreateProductCommand>
。只有当您明确指定TCommand
为CreateProductCommand
时,才能实现此目的的唯一方法如下:
ICommandHandler<CreateProductCommand> handler =
new CreateValidFriendlyUrlCommandHandler<CreateProductCommand>(
new CreateProductCommandHandler()
);
但是,Simple Injector无法“猜测”这个TCommand
应该是CreateProductCommand
,这就是为什么你的“装饰者”没有被包裹的原因。
长话短说:放弃TCommand
:
public class CreateValidFriendlyUrlCommandHandler
: ICommandHandler<CreateProductCommand>
{
private ICommandHandler<CreateProductCommand> decorated;
public CreateValidFriendlyUrlCommandHandler(
ICommandHandler<CreateProductCommand> decorated)
{
this.decorated = decorated;
}
public void Handle(CreateProductCommand command)
{
// logic here
}
}
或者使用类型约束使其具有通用性:
public class CreateValidFriendlyUrlCommandHandler<TCommand>
: ICommandHandler<TCommand>
where TCommand : CreateProductCommand
{
private ICommandHandler<TCommand> decorated;
public CreateValidFriendlyUrlCommandHandler(
ICommandHandler<TCommand> decorated)
{
this.decorated = decorated;
}
public void Handle(TCommand command)
{
// logic here
}
}
或删除类型约束并允许处理任何类型的命令,而不仅仅是CreateProductCommand
。
请注意,如果要定义许多只能处理一种特定类型命令处理程序的装饰器,您可能需要重新考虑策略。您的设计可能存在问题。