我正在寻找一些关于以下方面的更简洁的解决方案:在我的消息总线实现中,我有几个组件,当新消息发布到总线时订阅该事件。消息总线传输BusMessage对象(其值为object
)。每个组件还实现了处理特定总线消息的功能(派生组件可以覆盖某些消息类型的现有句柄功能),如下所述。对于传入的字符串类型的总线消息:
protected virtual void HandleMessage(BusMessage<string> msg) { ... }
为了将传入的消息分发到特定的句柄函数,我实现了
static bool TryClassify<T>(BusMessage msg, Action<BusMessage<T>> handleFunction)
接受T并检查给定BusMessage的方法是否实际上是BusMessage<T>
,意味着它的值是T类型。事件处理程序总是如下:
void HandleMessage(BusMessage msg)
{
if (BusMessage.TryClassify<string>(msg, HandleMessage)) return;
}
对于我想在组件中处理的每个特定BusMessage类型,我必须重复使用TryClassify的那一行 - 唯一的区别是我指定的类型,因为要使用的特定HandleMessage由编译器确定。我最终得到了一个由
组成的方法体if (BusMessage.TryClassify<string>(msg, HandleMessage)) return;
if (BusMessage.TryClassify<bool>(msg, HandleMessage)) return;
if (BusMessage.TryClassify<long>(msg, HandleMessage)) return;
if (BusMessage.TryClassify<int>(msg, HandleMessage)) return;
if (BusMessage.TryClassify<DateTime>(msg, HandleMessage)) return;
...
是否有更优雅,更时尚的方式,更少的样板代码来完成我需要的东西?使用类型{ typeof(string), typeof(bool), typeof(long), typeof(int), typeof(DateTime) }
数组的方向可能是什么?
答案 0 :(得分:1)
您可以使用表达式构建此代码:
class BusMessage
{
private static readonly Func<BusMessage,Delegate,bool> TryClass;
static BusMessage()
{
Type[] classTypes = new Type[]{typeof(int), typeof(string)};
MethodInfo mi = typeof(BusMessage).GetMethod("TryClassifyInternal", BindingFlags.NonPublic | BindingFlags.Static);
var p1 = Expression.Parameter(typeof(BusMessage));
var p2 = Expression.Parameter(typeof(Delegate));
Expression exp = null;
foreach(Type t in classTypes)
{
MethodInfo mig = mi.MakeGenericMethod(t);
Expression e = Expression.Call(mig, p1, Expression.Convert(p2, typeof(Action<>).MakeGenericType(typeof(BusMessage<>).MakeGenericType(t))));
if(exp == null)
{
exp = e;
}else{
exp = Expression.OrElse(exp, e);
}
}
TryClass = Expression.Lambda<Func<BusMessage,Delegate,bool>>(exp, p1, p2).Compile();
}
private static bool TryClassifyInternal<T>(BusMessage msg, Action<BusMessage<T>> handleFunction)
{
//former TryClassify code
return false;
}
public static bool TryClassify(BusMessage msg, Delegate handleFunction)
{
return TryClass(msg, handleFunction);
}
}
但是,在这种情况下,我希望您的原始代码清晰明了(如果您不想更改其他方法的代码,那么它可能是最短的。)