想象一下,我在某个服务器上有一个C#应用程序正在创建Item
类的实例并在消息传递服务上发布它们。
class Item
{
public int ID1, ID2, ID3;
public double Value1, Value2, Value3;
}
现在,我在台式机上有另一个C#应用程序,可以收听这些消息。我希望能够根据ID#字段的指定值创建回调。例如,“只要消息进入,ID1 = 2,ID2 = 160,ID3 =任何东西,就调用此方法”。我认为如果我使用字符串键值对,这将是直截了当的,但理想情况下我可以做到这一点而不放弃静态类型。我想这需要反思,但我不完全确定从哪里开始。
我正在想象应用创建一个Item
的实例,其中包含所需的ID#值(假设-1表示未指定),并将其传递给某个对象的RegisterCallback
方法{{1 }}。然后,只要ItemListener
收到新的ItemListener
消息,就可以检查匹配的任何回调,并采取相应的行动。这是一个合理的设计吗?关于如何实施它的任何建议?
答案 0 :(得分:3)
class ConditionalCallback()
{
public Predicte<Item> Predicate {get; set;}
public Action<Item> Callback {get; set;}
}
List<ConditionalCallback> callbacks = new List<ConditionalCallback>();
public AddCallBack(Predicte<Item> pred, Action<Item> callback)
{
callbacks.Add(new ConditionalCallback {
Predicate = pred,
Callback = callback
});
}
void HandleItem(Item item)
{
foreach(var cc in callbacks)
if (cc.Predicate(item))
cc.Callback(item);
}
//
AddCallBack( i=> i.ID1 = 2 && i.ID2 = 160 && i.ID3 = anything", MyCallback);
答案 1 :(得分:1)
可以不放弃类型安全。你基本上需要的是一个元组类型(.NET 4.0有这个,但如果你没有使用它,你可以轻松创建自己的),其中成员是你想要匹配的id类型的可空类型。
然后,您将使用这些类型的实例作为字典中的键,其中值是您将在匹配上执行的委托。例如,您的密钥类型如下所示:
struct ItemKey
{
public int? ID1, ID2, ID3;
public double? Value1, Value2, Value3;
}
然后,对于处理ID1 = 1,ID2 = 160和ID3 = any的消息的示例,您将在字典中实例化代理的密钥,如下所示:
new ItemKey { ID1 = 1, ID2 = 160 }
注意,这里的ItemKey是一个结构非常重要,因为它提供了正确的GetHashCode和Equals实现,这对于正确键入字典至关重要。
这种设计的一个缺点是你必须明确所有可能的部分匹配。
例如,如果您希望在ID1 = 2时处理委托,而在ID1 = 2且ID2 = 3时要处理另一个委托,则必须明确指定这些情况。如果您有许多排列,这可能会导致字典增长非常快。
如果是这种情况,您可能需要查看某种类型的数据库解决方案,其中将ID值存储在单独的列中,然后在相应的列上进行查找(筛选选择列)。然后,您将在该行的字段中具有类型名称,您可以使用该字段通过反射创建类型实例,该实例实现接口或从基类型派生,您可以创建变量并调用方法执行功能。