Передача делегата с аргументами шаблона в качестве параметра - PullRequest
0 голосов
/ 07 декабря 2010

Я борюсь с кодом ниже.

У меня есть метод Find, который для меня является универсальным в терминах, которые я могу использовать для разных типов, происходящих из одного и того же базового класса. Внутри этого метода я использовал делегат, передаваемый в вызов FindAll. Я удалил этот делегат и пытаюсь передать его как параметр, чтобы больше методов могли использовать метод Find с разными критериями фильтрации.

Проблема в том, что делегат фильтра должен иметь возможность принимать тип шаблона в качестве аргумента, а компилятор жалуется, что параметры метода Find не соответствуют . Проблема возникает внутри метода FindItems, когда я вызываю Find.

Есть идеи? Большое спасибо

    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;
    }

Ответы [ 3 ]

1 голос
/ 07 декабря 2010

Я вижу одну вещь: в вашем коде, где вы вызываете метод FindAll, вы пытаетесь использовать переменную фильтра в качестве метода.Уберите Паренов ...

Я делаю такие вещи постоянно.На самом деле я написал несколько общих процессов, подобных этому.

Делегат поиска должен соответствовать 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);

Я не скомпилировал это, и это всего лишь предположение, что два обобщенных типа имеют совпадающие значения, но я хотелпокажите эффект от того, как вы можете расширить это.

Однако, исходя из того, что я вижу в вашем коде, ваш фильтр должен работать, если вы удалите паренсы в вызове фильтра, поскольку он является делегатом в правильном шаблоне дляТип предиката.

1 голос
/ 07 декабря 2010

Я сделал некоторые изменения:

до FindItems, изменить f на FindFilter<BasicItem>:

    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));

и он компилируется; очевидно, я не могу проверить это, так как мне пришлось изобрести много кода ...

0 голосов
/ 07 декабря 2010

Спасибо за все комментарии, они мне очень помогли.В конце я просто изменил лямбда-вызов, предложенный Марком, так как не всегда хочу фильтровать:

List<T_Item> Items = tempList.FindAll(
                                                    delegate(T_Item itm) 
                                                        { 
                                                            if (filter == null) 
                                                                return true;
                                                            return filter(itm); 
                                                        }
                                                );
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...