使用温莎城堡IoC容器组件的注册时设置的名称属性 [英] Setting the Name property during registration of a component using Castle Windsor IoC container

查看:172
本文介绍了使用温莎城堡IoC容器组件的注册时设置的名称属性的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在我的应用程序有一个名为类的消息。存在类型为字符串的名称消息类型Message类的属性。该MessageType属性用来提醒应用程序,以什么数据模式将Message类的实例中存在。 Message类从名为即时聊天接口派生的。

In my application I have a class named Message. There exists a property in the Message class with the name MessageType of type string. The MessageType property is used to alert the application as to what data schema will exist within the instance of the Message class. The Message class derives from an interface named IMessage.

作为一个例子让我们说我们有消息类是谁的MessageType属性有com.business价值的一个实例。 product.RegisterUser。

As an example let's say we have an instance of the Message class who's MessageType property has the value of "com.business.product.RegisterUser".

每个消息类型架构中有相应的信息处理类(的MessageHandler)从接口派生IMessageHandler。另外,在上述例子的情况下,将有一个名为RegisterUserMessageHandler类。所有的消息处理程序类从IMessageHandler派生。 IMessageHandler定义了一个GetMessageType函数将返回派生消息实例的MessageType属性。

Each MessageType schema has a corresponding message handler class (MessageHandler) which derives from the interface IMessageHandler. In the case of the above example, there would be a class named RegisterUserMessageHandler. All message handler classes derive from IMessageHandler. IMessageHandler defines a GetMessageType function which will return the derived message instance’s MessageType property.

在类注册/与温莎城堡IoC容器组件我想设置的名称属性消息实例的消息类型属性的值。我也想注册这些类/使用注册通过公约组件的方法的组件来实现这一点。

During registration of the classes / components with the Castle Windsor IoC container I would like to set the Name property to the value of the Message instance’s MessageType property. I would also like to register these classes / components using the ‘register components by conventions’ method to accomplish this.

本练习的最终目的是为了让我的代码调用使用消息的消息类型属性来获取正确的消息处理程序实例Resolve方法。例如:

The ultimate purpose of this exercise is to allow my code to call the Resolve method using the MessageType property of the Message to obtain the correct message handler instance. For example:

字符串为messageType =com.business.product.RegisterUser;

IMessageHandler registerUserMessageHandler = _container.Resolve< IMessageHandler>(为messageType);

我将不胜感激任何帮助解决这个问题。非常感谢。

I would appreciate any help to solve this. Thanks very much.

推荐答案

这是我想出了一个解决方案,但它也有一些缺点。你必须决定是否缺点是您的情况可以接受的。然而,好处是配置基于惯例和增加新的即时聊天 IMessageHandler 类型将不需要任何额外的温莎配置。

Here's a solution I came up with, but it does have some drawbacks. You'll have to decide if the drawbacks are acceptable for your situation. However, the benefit is that configuration is based on convention and adding new IMessage and IMessageHandler types won't require any additional Windsor configuration.

我用的组合温莎的 TypedFactoryFacility 以及自定义 ITypedFactoryComponentSelector 。通过使用一个工厂,我删除了需要为你的代码直接调用容器的解析方法。当一个类需要获得 IMessageHandler 根据消息类型,它可以只对工厂的依赖。这里的工厂:

I used a combination of Windsor's TypedFactoryFacility along with a custom ITypedFactoryComponentSelector. By using a factory, I remove the need for your code to directly call the container's Resolve method. When a class needs to get an IMessageHandler based on a message type, it can just have a dependency on the factory. Here's the factory:

public interface IMessageHandlerFactory
{
    IMessageHandler GetMessageHandler(string messageType);
}



由于我使用温莎的 TypedFactoryFacility 我并不需要实现这个方法,但是当涉及到调用 GetMessageHandler 的方法,我会帮助温莎通过定义挑选适当的组件一个自定义组件选择:

Since I'm using Windsor's TypedFactoryFacility I don't need to implement this method, but when it comes to calling the GetMessageHandler method, I'll "help" Windsor pick the proper component by defining a custom component selector:

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);
    }
}

注册所有这一切就是这么简单:

Registering all of this is as simple as:

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()
    );

下面是一些测试代码我用来验证:

Here's some test code I used to verify:

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 ,他们将在温莎注册他们的全名)。如果你的消息处理程序是轻量级的和/或有没有很多人,或者他们是静态的,这可能不是一个问题。如果它们是瞬时和/或具有显著初始化代码,每一次解决所有这些需要一个单一的之一可以是昂贵的。在这种情况下,我会放弃这整个的做法,并与东西是更多的配置为重,但允许通过名称直接解析一个消息处理程序走。

Now, the drawback: Inside the component selector, I resolve all IMessageHandler's and then decide which one to use based on the name (since I didn't name the message handlers when registering them, they'll be registered in Windsor with their fully qualified name). If your message handlers are lightweight and/or there's not many of them, or they're static, this might not be an issue. If they are transient and/or have significant initialization code, resolving all of them every time you need a single one could be costly. In that case, I'd scrap this whole approach and go with something that is more configuration-heavy, but allows resolving a single message handler directly by name.

这篇关于使用温莎城堡IoC容器组件的注册时设置的名称属性的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆