这是我提出的解决方案,但它确实有一些缺点。您必须决定这些缺点是否适合您的情况。但是,好处是配置基于约定,并且添加新的IMessage
和IMessageHandler
类型将不需要任何额外的Windsor配置。
我使用了温莎的TypedFactoryFacility
以及自定义ITypedFactoryComponentSelector
的组合。通过使用工厂,我不再需要您的代码来直接调用容器的Resolve
方法。当一个类需要基于消息类型获得IMessageHandler
时,它只能依赖于工厂。这里的工厂:
public interface IMessageHandlerFactory
{
IMessageHandler GetMessageHandler(string messageType);
}
由于我使用温莎TypedFactoryFacility
我并不需要实现这个方法,但是当涉及到调用GetMessageHandler
方法,我会“帮助”温莎通过挑选合适的组件定义一个自定义组件选择:
public class HandlerTypeSelector : DefaultTypedFactoryComponentSelector
{
private readonly WindsorContainer container;
public HandlerTypeSelector(WindsorContainer container)
{
this.container = container;
}
protected override string GetComponentName(MethodInfo method, object[] arguments)
{
if (method.Name == "GetMessageHandler")
{
var type = arguments[0].ToString();
var messageHandlers = container.ResolveAll<IMessageHandler>();
var single = messageHandlers.SingleOrDefault(h => h.GetMessageType() == type);
if(single != null)
return single.GetType().FullName;
}
return base.GetComponentName(method, arguments);
}
}
注册这一切很简单,只要:
var container = new WindsorContainer();
container.AddFacility<TypedFactoryFacility>();
container.Register(
Component.For<IMessageHandlerFactory>().AsFactory(c => c.SelectedWith(new HandlerTypeSelector(container))),
AllTypes.FromThisAssembly().BasedOn<IMessage>().WithService.AllInterfaces(),
AllTypes.FromThisAssembly().BasedOn<IMessageHandler>().WithService.AllInterfaces()
);
这是我用来验证一些测试代码:
var sampleMessage = new RegisterUserMessage();
var factory = container.Resolve<IMessageHandlerFactory>();
var handler = factory.GetMessageHandler(sampleMessage.MessageType);
而且我用测试类/接口:现在
public interface IMessage
{
string MessageType { get; }
}
public interface IMessageHandler
{
string GetMessageType();
}
public class RegisterUserMessage : IMessage
{
public string MessageType
{
get { return "RegisterUser"; }
}
}
public class RegisterUserMessageHandler : IMessageHandler
{
public string GetMessageType()
{
return "RegisterUser";
}
}
public class RemoveUserMessage : IMessage
{
public string MessageType
{
get { return "RemoveUser"; }
}
}
public class RemoveUserMessageHandler : IMessageHandler
{
public string GetMessageType()
{
return "RemoveUser";
}
}
,其缺点:内部组件选择,我解决所有IMessageHandler
的,然后再决定使用哪一个基于名称(因为我没有在注册时给消息处理程序命名,所以它们将以其完全合格的名称在Windsor中注册)。如果你的消息处理器是轻量级的,并且/或者它们不是很多,或者它们是静态的,这可能不是问题。如果它们是暂时的和/或有重要的初始化代码,那么每次需要单个代码时解决它们可能代价很高。在这种情况下,我会放弃整个方法,并使用更多配置的东西,但可以直接按名称解析单个消息处理程序。
我看到的挑战是messageType(来自您的描述)是一个实例字段。当你注册组件时,你只是在处理类型信息 - 而不是实际的实例。或者messageType是静态的? – PatrickSteele
嗨帕特里克。消息类型是一个常量,因此可以通过多种方式进行定义。类中的私有静态常量字符串是定义它的好方法。我还注意到示例代码中的“参数”的引用。我不确定什么属性是或表示的,但它看起来好像它可能是一个.NET类属性。不确定,但希望任何人都可以提供的信息。 –