繁体   English   中英

C#-如何将对象映射到适合该对象类型的通用类?

[英]C# - How to map an object to a generic class suited to that object type?

(我确实想出一个更好的标题,随时可以编辑)

假设我有一个通用的事件处理程序接口和实现:

public interface IEventHandler<T>
{
    void HandleEvent(T t);
}

public class SlowButAccurateEventHandler<T> : IEventHandler<T>
{
    // To emphasize that the implementation depends on T
    private void SomeHelperClass<T> helperClass;

    public void HandleEvent(T t) { ... }
}

public class FastEventHandler<T> : IEventHandler<T>
{
    // To emphasize that the implementation depends on T
    private void SomeHelperClass<T> helperClass;

    public void HandleEvent(T t) { ... }
} 

和另一个我想保存EventHandlers实例的类,但是不能使用通用方法,因为它是WCF服务:

public class MyService : MyContract
{
    // Pseudo (doesn't compile)
    private Dictionary<Type, IEventHandler<T>> eventHandlers;

    public MyService()
    {
        // More pseudo...
        eventHandlers = new Dictionary<Type, IEventHandler<T>>()
        {  
            { typeof(string), new SlowButAccurateEventHandler<string>() },
            { typeof(int), new FastEventHandler<int>() },
        };    
    }
    public void RouteToEventHandler(object userEvent)
    {
       var handler = eventHandlers[typeof(userEvent))];
       handler.HandleEvent(userEvent); // I realize that userEvent needs to be converted here
    }
}

因此,基本上,我有一些服务( MyService ),我想保留IEventHandlers并在事件到达时调度正确的处理程序。 为此,我想保留一个字典,其中包含CLR类型和适当的IEventHandler之间的映射。 那可能吗?

您应该这样定义您的界面:

public interface IEventHandler<T>
{
    void HandleEvent(object t);
}

然后在执行中:

public class FastEventHandler<T> : IEventHandler<T>
{
    // To emphasize that the implementation depends on T
    private void SomeHelperClass<T> helperClass;

    public void HandleEvent(object t)
    {
        if (t == null || !Type.Equals(t.GetType(), typeof(T)))
        {
            // We cannot handle the event.
            return;
        }

        T typedValue = Convert(t);

        // Here comes the rest of handling process.
    }

    private T Convert(object value)
    {
        try
        {
            return (T)value;
        }
        catch
        {
            return default(T);
        }
    }
} 

另一个实现,但是我会留在以前的答案中:

public interface IEventHandler
{
    void HandleEvent(object value);
}

public interface IEventHandler<T> : IEventHandler
{
    void HandleEvent(T value);
}

public abstract class EventHandler<T> : IEventHandler<T>
{
    public void HandleEvent(object value)
    {
        if (value == null || !Type.Equals(value.GetType(), typeof(T)))
        {
            return;
        }

        HandleEvent(Convert(value));
    }

    private T Convert(object value)
    {
        try
        {
            return (T)value;
        }
        catch
        {
            return default(T);
        }
    }

    public abstract void HandleEvent(T value);
}

public class FastEventHandler<T> : EventHandler<T>
{
    public override void HandleEvent(T value)
    {
        throw new NotImplementedException();
    }
}

在构造函数中,您可以初始化事件处理程序:

var handlers = new Dictionary<Type, IEventHandler>()
{
    { typeof(string), new FastEventHandler<string>() },
    { typeof(int), new FastEventHandler<int>() }
};

然后:

public void RouteToEventHandler(object userEvent)
{
    if (userEvent == null)
    {
        return;
    }

    var handler = handlers[userEvent.GetType()];

    handler.HandleEvent(userEvent);
}

当然,一种方法是将处理程序存储在Dictionary<Type, object> ,然后使用反射来调用所需的方法。 如果您对单个方法感兴趣(例如您的示例),则可以构建并存储对该方法的委托调用,如下所示:

public class MyService : MyContract
{
    private Dictionary<Type, Action<object>> eventHandlers;

    static Action<object> GetHandler<T>(IEventHandler<T> handler)
    {
        var parameter = Expression.Parameter(typeof(object), "t");
        var body = Expression.Call(
            Expression.Constant(handler),
            "HandleEvent", null,
            Expression.Convert(parameter, typeof(T)));
        return Expression.Lambda<Action<object>>(body, parameter).Compile();
    }

    public MyService()
    {
        eventHandlers = new Dictionary<Type, Action<object>>()
        {
            { typeof(string), GetHandler(new SlowButAccurateEventHandler<string>()) },
            { typeof(int), GetHandler(new FastEventHandler<int>()) },
        };
    }

    public void RouteToEventHandler(object userEvent)
    {
        Action<object> handler;
        if (eventHandlers.TryGetValue(userEvent.GetType(), out handler))
            handler(userEvent);
    }
}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM