2016-11-22 2 views
1

Ich habe eine generische Methode, die die letzte Datensatz aus einer Tabelle zurückgeben soll:Aufruf generische Methode mit Expression durch Reflexion

public T FindLast<TKey>(Expression<Func<T,TKey>> specification = null) 
{ 
    return specification == null 
     ? Set().LastOrDefault() 
     : Set().OrderBy(specification).LastOrDefault(); 
} 

Ich brauche es durch

Reflexion nennen
var methodCreateReadRepositoryAttr = (entityMetadata.GetEntityAttributeType() != null) ? 
typeof(IRepositoryFactory).GetMethod("CreateReadRepository").MakeGenericMethod(entityMetadata.GetEntityAttributeType()) : null; 

var methodEntityGet3 = attributeReadRepository.GetType().GetMethod("FindLast", new Type[] { typeof(Expression<Func<ArticleAttribute,int>>) }); 

Aber im Debug methodEntityGet3 ist Null. Was habe ich falsch gemacht?

+0

Sind es zu nennen Sie in der Lage, ohne Reflexion? –

Antwort

0

Sie benötigen eine Methode zu brechen in zwei Aufruf:

var methodEntityGet3 = attributeReadRepository.GetType().GetMethod("FindLast"); 
var closedGenericMethod = methodEntity3.MakeGenericMethod(new Type[] { typeof(Expression<Func<ArticleAttribute,int>>) }; 
1

Das Problem besteht darin, dass Sie eine Methode mit dem geschlossenen Typ anfordern, während die Methode FindLast generisch ist und einen offenen Typ hat, d. H. Der Typ des Parameters ist Expression<Func<T, TKey>> und nicht der von Ihnen angegebene Typ. Das Reflexionssystem wird nicht gehen und die generische Methode erstellen, die am besten passt, da dies von den Regeln in der Sprache abhängen kann. Sie können erreichen, dass die Argumente in dynamic konvertieren, aber ich bin mir nicht genau darüber sicher.

Außerdem gibt es keine einfache Möglichkeit, die Typparameter T und TKey zu erhalten. Daher würde ich vorschlagen, dass Sie die Methode nur mit ihrem Namen durchsuchen und dann die generische Methode wie bei der obigen Methode explizit erstellen.

Edit: Eigentlich funktioniert die dynamic Lösung tatsächlich und ist wahrscheinlich viel lesbarer als jede Reflexion Anruf sein kann. Der folgende Code kompiliert und gibt, was zu erwarten ist:

class Program 
{ 
    static void Main(string[] args) 
    { 
     var foo = new Foo<string>(); 
     Expression<Func<string, int>> arg = s => s.Length; 
     CallFindLast(foo, arg); 
     Console.Read(); 
    } 

    private static void CallFindLast(Foo<string> foo, object arg) 
    { 
     var dynamicArg = (dynamic)arg; 
     foo.FindLast(dynamicArg); 
    } 

    private class Foo<T> 
    { 
     public T FindLast<TKey>(Expression<Func<T, TKey>> specification = null) 
     { 
      Console.WriteLine($"T: {typeof(T).Name}, TKey: {typeof(TKey).Name}"); 
      return default(T); 
     } 
    } 
} 
Verwandte Themen