大家好,
我有问题,我有这样的界面:
public interface ICommand<in TRequest, out TResponse>
where TRequest : class
where TResponse : BaseResponse
{
TResponse Execute(TRequest request);
}
然后我通过两个类来实现此接口,如下所示:
public class ExternalAddUser : ICommand<ExternalAddUserRequest, ExternalAddUserResponse>
{
private readonly ICommand<AddUserRequest, AddUserResponse> _command;
public ExternalAddUser(ICommand<AddUserRequest, AddUserResponse> command)
{
_command = command;
}
public ExternalAddUserResponse Execute(ExternalAddUserRequest request)
{
var response = _command.Execute(Mapper.Map<AddUserRequest>(request));
return Mapper.Map<ExternalAddUserResponse>(response);
}
}
还有:
public class AddUser : ICommand<AddUserRequest, AddUserResponse>
{
private readonly IUnitOfWork _unitOfWork;
private readonly IMessageService _messageService;
private readonly IDefaultSettings _settings;
private readonly IMessageFactory _messageFactory;
public AddUser(IUnitOfWork unitOfWork, IMessageService messageService, IDefaultSettings settings, IMessageFactory messageFactory)
{
_unitOfWork = unitOfWork;
_messageService = messageService;
_settings = settings;
_messageFactory = messageFactory;
}
public AddUserResponse Execute(AddUserRequest request)
{
// My implementation here
}
}
接口IMessageFactory是一个“工厂/模板”模式,该模式创建一个仅具有以下属性的IMessage接口:正文,主题,语言。 我已经使用简单的注射器注册了我的课程,如下所示:
container.Register(typeof(ICommand<,>), businessLayerAssembly);
container.Register<IDefaultSettings, DefaultSettings>(Lifestyle.Singleton);
container.Register<ISecuritySettings, SecuritySettings>(Lifestyle.Singleton);
container.RegisterConditional<IMessageFactory, ActivationMessageFactory>
(c => c.Consumer.ImplementationType == typeof(AddUser)
|| c.Consumer.ImplementationType == typeof(SendActivationEmail));
container.RegisterConditional<IMessageFactory, RecoveryMessageFactory>
(c => !c.Handled);
现在,我有另一个类是ActivationMessageFactory的装饰器,如下所示:
public class ActivationMessageWithoutLinkFactory : IMessageFactory
{
private readonly IMessageFactory _messageFactory;
public ActivationMessageWithoutLinkFactory(IMessageFactory messageFactory)
{
_messageFactory = messageFactory;
}
public IMessage CreateMessage(MessageData messageData)
{
// Implementation
}
}
我的问题是:
从ExternalAddUser类调用此类时,是否可以在AddUser类中注入ActivationMessageWithoutLinkFactory装饰器?
气味代码示例:
public class ExternalAddUser : ICommand<ExternalAddUserRequest, ExternalAddUserResponse>
{
public ExternalAddUserResponse Execute(ExternalAddUserRequest request)
{
ICommand<AddUserRequest, AddUserResponse> command = new AddUser(new SqlUnitOfWork(), new EmailService(),
new DefaultSettings(), new ActivationMessageWithoutLinkFactory(new ActivationMessageFactory()));
}
}
谢谢您的回答,我希望我很清楚。
答案 0 :(得分:1)
您要实现的目标是根据消费者的消费者应用装饰器。这在Simple Injector中无法轻松实现。相反,您可以尝试以下操作:不必使装饰器成为条件接收器,而向其注入可以在请求开始时设置的上下文数据。装饰者可以通过这种方式决定是否应执行其逻辑,或者只需将调用转发给被装饰者。
更新:
您可以定义以下抽象:
public class ICommandContext
{
Type RootRequest { get; }
}
此抽象允许您检查当前正在运行的根请求的类型。您可以在装饰器中使用此抽象:
public class ActivationMessageWithoutLinkFactory : IMessageFactory
{
private readonly ICommandContext _context;
private readonly IMessageFactory _messageFactory;
public ActivationMessageWithoutLinkFactory(
ICommandContext context,
IMessageFactory messageFactory)
{
_context = context;
_messageFactory = messageFactory;
}
public IMessage CreateMessage(MessageData messageData)
{
if (_context.RootRequest == typeof(ExternalAddUser))
{
// Begin decorated stuff
var message = _messageFactory.CreateMessage(messageData);
// End decorated stuff
return message;
}
else
{
return _messageFactory.CreateMessage(messageData);
}
}
}
现在,在您的“合成根”内部,可以创建一个ICommandContext
实现和一个ICommand<,>
装饰器来管理此上下文:
public class CommandContext : ICommandContext
{
public Stack<Type> Requests = new Stack<Type>();
public Type RootRequest => Requests.First();
}
public class ContextCommandDecorator<TRequest, TResponse> : ICommand<TRequest, TResponse>
{
private readonly CommandContext _context;
private readonly ICommand<TRequest, TResponse> _decoratee;
public ContextCommandDecorator(
CommandContext context,
ICommand<TRequest, TResponse> decoratee)
{
_context = context;
_decoratee = decoratee;
}
public TResponse Execute(TRequest request)
{
_context.Push(typeof(TRequest));
try
{
return _decoratee.Execute(request);
}
finally
{
_context.Pop();
}
}
}
最后,您可以将以下三个注册添加到您的应用程序中:
container.Register<ICommandContext, CommandContext>(Lifestyle.Scoped);
container.Register<CommandContext>(Lifestyle.Scoped);
container.RegisterDecorator(typeof(ICommand<,>), typeof(ContextCommandDecorator<,>));