C# 简单注入器开放泛型装饰器
我试图利用simple injector中的一些优秀功能 我目前和装饰师有问题,他们没有受到打击,当我期待他们太多 我是这样注册的:C# 简单注入器开放泛型装饰器,c#,.net,dependency-injection,ioc-container,simple-injector,C#,.net,Dependency Injection,Ioc Container,Simple Injector,我试图利用simple injector中的一些优秀功能 我目前和装饰师有问题,他们没有受到打击,当我期待他们太多 我是这样注册的: container.RegisterManyForOpenGeneric( 类型(ICommandHandler), AppDomain.CurrentDomain.GetAssemblys()); container.RegisterDecorator( 类型(ICommandHandler), 类型(CreateValidFriendlyUrlCommandH
container.RegisterManyForOpenGeneric(
类型(ICommandHandler),
AppDomain.CurrentDomain.GetAssemblys());
container.RegisterDecorator(
类型(ICommandHandler),
类型(CreateValidFriendlyUrlCommandHandler),
context=>context.ServiceType==typeof(ICommandHandler)
);
container.RegisterDecorator(
类型(ICommandHandler),
typeof(CreateProductValidationCommandHandler),
context=>context.ServiceType==typeof(ICommandHandler)
);
我想我一定遗漏了什么,因为我希望对ICommandHandler
的调用在运行自身之前将调用CreateValidFriendlyUrlCommandHandler
和CreateProductValidationCommandHandler
我尝试过以下不同的注册方式:
container.RegisterManyForOpenGeneric(
类型(ICommandHandler),
AppDomain.CurrentDomain.GetAssemblys());
container.RegisterDecorator(
类型(ICommandHandler),
类型(CreateValidFriendlyUrlCommandHandler),
context=>context.ImplementationType==typeof(CreateProductCommandHandler)
);
container.RegisterDecorator(
类型(ICommandHandler),
typeof(CreateProductValidationCommandHandler),
context=>context.ImplementationType==typeof(CreateProductCommandHandler)
);
当CreateProductValidationCommandHandler
和CreateValidFriendlyUrlCommandHandler
实现ICommandHandler
时,我认为在类型ICommandHandler
上注册ICommandHandler
的修饰符可能会遇到一些循环引用
但改变这一点没有什么区别
这是我的CreateProductValidationCommandHandler
:
公共类CreateProductValidationCommandHandler
:ICommandHandler
{
私有只读ICommandHandler;
私有只读IValidationService validationService;
公共CreateProductValidationCommandHandler(
ICommandHandler,
IValidationService验证服务)
{
这是装饰过的;
this.validationService=validationService;
}
公共无效句柄(CreateProductCommand)
{
如果(!validationService.IsValidFriendlyName)(
command.Product.ProductFriendlyUrl)
{
command.ModelStateDictionary.AddModelError(
“ProductFriendlyUrl”,
“友好的产品名称无效…”);
返回;
}
如果(!validationService.IsUniqueFriendlyName(
command.Product.ProductFriendlyUrl)
{
command.ModelStateDictionary.AddModelError(
“ProductFriendlyUrl”,
“友好的产品名称是……”);
返回;
}
}
}
这是我的CreateValidFriendlyUrlCommandHandler
:
公共类CreateValidFriendlyUrlCommandHandler
:ICommandHandler
{
私有只读ICommandHandler;
public CreateValidFriendlyUrlCommandHandler(ICommandHandler)
{
这是装饰过的;
}
公共无效句柄(CreateProductCommand)
{
if(string.IsNullOrWhiteSpace)(
command.Product.ProductFriendlyUrl)
{
command.Product.ProductFriendlyUrl=
MakeFriendlyUrl(command.Product.Name);
}
}
}
问题在于,Simple Injector将永远无法将ICommandHandler
实现包装到您的一个装饰器中,因为存在无法解决的泛型类型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)
{
// This won't compile since CreateProductCommand and
// TCommand are not related.
this.decorated.Handle(command);
}
}
不过,简单的Injector无法“猜测”这个t命令应该是CreateProductCommand
,这就是为什么您的“decorator”没有包装好
长话短说:扔掉t命令
:
public class CreateValidFriendlyUrlCommandHandler
: ICommandHandler<CreateProductCommand>
{
private ICommandHandler<CreateProductCommand> decorated;
public CreateValidFriendlyUrlCommandHandler(
ICommandHandler<CreateProductCommand> decorated)
{
this.decorated = decorated;
}
public void Handle(CreateProductCommand command)
{
// logic here
}
}
公共类CreateValidFriendlyUrlCommandHandler
:ICommandHandler
{
私人ICommandHandler;
公共CreateValidFriendlyUrlCommandHandler(
ICommandHandler(已装饰)
{
这是装饰过的;
}
公共无效句柄(CreateProductCommand)
{
//这里的逻辑
}
}
或者使用类型约束使其成为泛型:
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
}
}
公共类CreateValidFriendlyUrlCommandHandler
:ICommandHandler
其中TCommand:CreateProductCommand
{
私人ICommandHandler;
公共CreateValidFriendlyUrlCommandHandler(
ICommandHandler(已装饰)
{
这是装饰过的;
}
公共无效句柄(TCommand命令)
{
//这里的逻辑
}
}
或者删除类型约束并允许处理任何类型的命令,而不仅仅是CreateProductCommand
请注意,如果要定义多个装饰器,而这些装饰器只能处理一种特定类型的命令处理程序,则可能需要重新考虑您的策略。您的设计可能有问题。您的装饰程序不应是通用的。事实上,从技术上讲,它们不是装饰程序:-)请注意,Appdomain.CurrentDomain.GeAssemblies
仅返回已加载的程序集。如果所有实现都与ICommandHandler
位于同一个程序集中,则不会有问题,但要小心。好吧,这是有道理的,我所做的一些事情就是让它按我想要的方式工作。我有一个开放的通用注册,并希望一些装饰,但我只希望他们应用时,命令
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
}
}