2010-12-07 7 views
0

Je suis aux prises avec le code ci-dessous.Passer le délégué avec les arguments de modèle comme paramètre

J'ai une méthode Find, qui pour moi est générique en termes je peux l'utiliser pour différents types dérivant de la même classe de base. À l'intérieur de cette méthode j'avais un délégué passé à l'appel FindAll. J'ai supprimé ce délégué et j'essaie de le passer en paramètre, donc plus de méthodes peuvent utiliser la méthode Find avec différents critères de filtrage. Le problème est que le délégué de filtre doit être en mesure d'accepter un type de modèle en tant qu'argument, et le compilateur se plaint que les paramètres de la méthode Find ne correspondent pas à. Le problème se produit dans la méthode FindItems lorsque j'appelle Find.

Des idées? Un grand merci

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

Qu'est-ce que T_Item, pouvez-vous poster plus de code? – TalentTuner

+0

T_Item est le type de modèle. Cela peut être n'importe quel élément dérivant de MailItemId, comme Letter par exemple – Andres

Répondre

1

J'ai fait quelques changements:

à FindItems, changer f-FindFilter<BasicItem>:

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

et Find, utilisez le type générique FindFilter:

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

et a changé la ma à la recherche:

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

et il compile; évidemment je ne peux pas le tester puisque j'ai dû inventer beaucoup de code ...

+0

Bon, mais maintenant le problème se produit lorsque j'essaie d'appeler le délégué: Liste Items = tempList.FindAll (filter (T_Item itm)); Désolé de ne pas poster plus de code, c'est parce que son énorme – Andres

+0

@Andres - désolé, j'ai raté un changement que j'ai ajouté; voir ci-dessus –

1

Une chose que je vois est que dans votre code où vous appelez la méthode FindAll vous essayez d'utiliser la variable de filtre comme méthode. Enlevez les Parens ...

Je fais des trucs comme ça tout le temps. En fait, j'ai écrit plusieurs processus génériques similaires à celui-ci.

Le délégué find doit correspondre à Predicate afin que toute méthode qui effectue cela le fasse. Par exemple, disons que vous vouliez faire quelque chose de fou, comme la réflexion sur l'utilisation de votre filtre, vous pourriez faire quelque chose comme ça.

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

Ensuite, votre liste utiliserait comme si directement:

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

ou dans le cas de votre méthode où vous avez passé dans le délégué prédicat déjà défini:

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

I Je n'ai pas compilé cela et c'est juste une supposition que les deux génériques ont des valeurs correspondantes, mais je voulais montrer l'effet de comment vous pouvez étendre cela.

Cependant, d'après ce que je peux voir dans votre code, votre filtre devrait fonctionner si vous supprimez les parens de votre appel de filtre, puisqu'il s'agit d'un délégué dans le modèle correct pour le type de prédicat.

+0

merci pour les idées ;-) – Andres

0

Merci pour tous les commentaires, ils m'ont beaucoup aidé.A la fin, je viens de changer l'appel lambda proposé par Marc ne pas toujours que je veux filtrer:

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