(我真的试图想出一个更好的标题,随时编辑)
假设我有一个通用的事件处理程序接口和实现:
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之间映射的字典。这可能吗?
答案 0 :(得分:0)
您应该像这样定义您的界面:
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);
}
}
}
答案 1 :(得分:0)
另一种实现方式,但我会保留以前的答案:
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);
}
答案 2 :(得分:0)
当然,一种方法是将处理程序存储在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);
}
}