根据具有特定值的特定字段创建操作

时间:2010-02-17 19:11:17

标签: c# reflection callback

想象一下,我在某个服务器上有一个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消息,就可以检查匹配的任何回调,并采取相应的行动。这是一个合理的设计吗?关于如何实施它的任何建议?

2 个答案:

答案 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值存储在单独的列中,然后在相应的列上进行查找(筛选选择列)。然后,您将在该行的字段中具有类型名称,您可以使用该字段通过反射创建类型实例,该实例实现接口或从基类型派生,您可以创建变量并调用方法执行功能。