【问题标题】:Passing delegate with template args as parameter使用模板 args 作为参数传递委托
【发布时间】:2010-12-07 10:25:00
【问题描述】:

我正在为下面的代码苦苦挣扎。

我有一个方法 Find,它对我来说是通用的,我可以将它用于从同一个基类派生的不同类型。在这个方法中,我曾经有一个委托传递给 FindAll 调用。我删除了这个委托,并尝试将其作为参数传递,因此更多方法可以使用具有不同过滤条件的 Find 方法。

问题在于过滤器委托必须能够接受模板类型作为参数,而编译器抱怨 Find 方法的参数不匹配。当我调用 Find 时,问题发生在方法 FindItems 内部。

有什么想法吗?非常感谢

    delegate bool FindFilter<T_Item>(T_Item item);

    private List<MailItem> Find<T_Item, T_Adaptor>(T_Adaptor adaptor, MailItemId mailId, FindFilter filter)
    {
            List<T_Item> tempList = ((List<T_Item>)(typeof(T_Adaptor).InvokeMember(
                    "Load",
                    BindingFlags.DeclaredOnly | BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.InvokeMethod,
                    null, adaptor,
                    new Object[] { null, mailId, null })));

            totalItemsFound = tempList.Count;

            List<T_Item> Items = tempList.FindAll(
                            filter()
                        );

        List<MailItem> mailItems = new List<MailItem>();
        foreach (T_Item itm in Items)
            mailItems.Add(itm as MailItem);

        return mailItems;
    }

        private static bool FindAssignedItemsOnly<T_Item>(T_Item itm)
        {
            MailItem mi = itm as MailItem;
            if (mi == null) return false;
            return (mi.StateInd.Code == StateInd.ASSIGNED);
        }

    public List<MailItem> FindItems(MailItemId itemId, string mailCategoryCd)
    {
        List<MailItem> mailItems = new List<MailItem>();

            FindFilter<MailItem> f = FindAssignedItemsOnly;
           // Problem happens in the line below
            mailItems = Find<Letter, BasicItemAdapter>(new LetterItemAdapter(), itemId, f); 

        return mailItems;
    }

【问题讨论】:

  • 什么是 T_Item ,能多发些代码吗?
  • T_Item 是模板类型。它可以是从 MailItemId 派生的任何项目,例如 Letter

标签: c# generics delegates


【解决方案1】:

我做了一些改动:

改为FindItems,将f改为FindFilter&lt;BasicItem&gt;

    FindFilter<BasicItem> f = FindAssignedItemsOnly;
    // Problem happens in the line below
    mailItems = Find<BasicItem, BasicItemAdapter>(new BasicItemAdapter(), itemId, f);

对于Find,使用FindFilter 泛型类型:

 private List<MailItem> Find<T_Item, T_Adaptor>(T_Adaptor adaptor,
    MailItemId mailId, FindFilter<T_Item> filter)

并更改了主搜索:

List<T_Item> Items = tempList.FindAll(row => filter(row));

然后编译;显然我无法测试它,因为我必须发明很多代码......

【讨论】:

  • 很好,但现在当我尝试调用委托时出现问题: List Items = tempList.FindAll( filter(T_Item itm) );很抱歉没有发布更多代码,因为它很大
  • @Andres - 抱歉,我错过了我添加的更改;见上文
【解决方案2】:

我看到的一件事是,在您调用 FindAll 方法的代码中,您试图将过滤器变量用作方法。删除括号...

我一直都在做这样的事情。事实上,我已经编写了几个类似的通用流程。

find 委托必须匹配 Predicate,所以任何这样做的方法都会这样做。例如,假设你想做一些疯狂的事情,比如为你的过滤器使用反射,你可以做这样的事情。

public class SimpleFind<T_Adaptor, T_Item>
{
   public T_Adaptor AdapterItem { get; set; }
   public SimpleFind(T_Adaptor item)
   {
      this.AdapterItem = item;
   }

   public bool FindMyStuff<T_Item>(T_Item value)
   {
      // Place your crazy reflection logic here...
      if (value.Property == AdapterItem.Property) return true;
      else return false;
   }
}

那么你的列表会直接使用它:

List<T_ITem> items = myItems.Find(new SimpleFind<T_Adaptor, T_Item>(adapterValue).Find);

或者在你的方法中你已经定义了谓词委托:

List<T_ITem> items = myItems.Find(filter);

我没有编译这个,这只是假设两个泛型具有匹配的值,但我想展示如何扩展它的效果。

但是,根据我在您的代码中看到的内容,如果您删除过滤器调用中的括号,您的过滤器应该可以工作,因为它是 Predicate 类型的正确模式的委托。

【讨论】:

    【解决方案3】:

    感谢所有的 cmets,他们帮助了我很多。最后,我只是更改了 Marc 建议的 lambda 调用,因为我并不总是想过滤:

    List<T_Item> Items = tempList.FindAll(
                                                        delegate(T_Item itm) 
                                                            { 
                                                                if (filter == null) 
                                                                    return true;
                                                                return filter(itm); 
                                                            }
                                                    );
    

    【讨论】:

      猜你喜欢
      • 2013-11-17
      • 2011-05-29
      • 2015-03-06
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多