2016-11-17 2 views
0

lI die folgende Funktion haben:ausschließen generische Funktion zur Laufzeit Property

private static Expression<Func<TEntity, TValue>> BuildLambda<TEntity, TValue>(string property) where TEntity : class 
     { 
      var param = Expression.Parameter(typeof (TEntity), "e"); 
      var prop = Expression.PropertyOrField(param, property); 
      return Expression.Lambda<Func<TEntity, TValue>>(prop, param); 
     } 

ich um mit Reflexionen spiele:

Wie diese Funktion zur Laufzeit mit einem dynamischen TEntity und TValue ausschließen. Ist es überhaupt möglich?

Beispiel:

public static void ValidateEntity<TEntity>(AbstractValidator<TEntity> validator,PropertyRule propRule) where TEntity : class, new() 
     { 
      var propertyName = propRule.Expression.GetMember().Name; 
      var propType = typeof(TEntity).GetProperty(propertyName); 
      //trying to exclude BuildLamdba don't know TValue only have PropertyInfo 
      //var expresssion = BuildLambda<TEntity, IEnumerable<TValue>>(propertyName); 

.... 
} 
+0

Dort finden Sie Erleuchtung: http://StackOverflow.com/Questions/232535/How-Do-I-use-Reflektion-zu-Call-a-generic-Method – csharpfolk

+0

@ Csharpfolk Das einzige Problem mit der Verbindung, die Sie zur Verfügung stellen, ist Wenn die Funktion aufgerufen wird, gibt sie immer ein Objekt zurück, nicht Expression >. Was ich nach dem Aufruf dieser Funktion mache, löst einen Fehler aus, weil der Typ Objekt Expression > ist. Auch wenn ich versuche, mit Convert.ChangeType zu konvertieren, habe ich das gleiche Problem mit der Rückgabe eines Objekts anstelle von Expression >. – Valter

Antwort

0

Es war wirklich schwer zu verstehen, was das Problem sein kann, wenn ich nicht richtig erraten haben Sie runnable Codebeispiel mit .NET Fiddle oder ähnliche Website zur Verfügung stellen:

namespace Foo { 

using System; 
using System.Collections.Generic; 
using System.Linq; 
using System.Linq.Expressions; 
using System.Reflection; 



public class Program 
{ 
    public static void Main() 
    { 
     var parent = new Parent { 
      Children = new List<Child> { 
       new Child(), 
       new Child(), 
       new Child() 
      } 
     }; 

     { 
     // works 

     var expr = BuildLambda<Parent, IEnumerable<Child>>("Children"); 

     expr.Compile().Invoke(parent).ToList().ForEach(x => Console.WriteLine(x)); 
     } 

     // works too 
     { 

     var expr2 = BuildLambda<Parent, IEnumerable<object>>("Children"); 

     expr2.Compile().Invoke(parent).ToList().ForEach(x => Console.WriteLine(x)); 
     } 

     // and this works too 
     ValidateEntity(parent); 

    } 


    public static void ValidateEntity<TEntity>(TEntity e) 
     where TEntity : class, new() 
     { 
      var propertyName = "Children"; 
      var propType = typeof(TEntity).GetProperty(propertyName); 


      var expr = typeof(Program) 
       .GetMethod("BuildLambda", BindingFlags.Public | BindingFlags.Static) 
       .MakeGenericMethod(new[] { typeof(TEntity), propType.PropertyType }) 
       .Invoke(null, new[] {propertyName}); 

      // Here we invoke artificial method and inject property type there 
      typeof(Program).GetMethod("ProcessExpr") 
       .MakeGenericMethod(new[] { typeof(TEntity), propType.PropertyType }) 
       .Invoke(null, new [] { expr, e }); 

     } 


    public static void ProcessExpr<TEntity, TValue>(Expression<Func<TEntity, TValue>> expr, TEntity parent) { 
     // here we know both types 
     Console.WriteLine("Yay works too!"); 
     ((IEnumerable<Child>)expr.Compile().Invoke(parent)).Cast<Child>().ToList().ForEach(x => Console.WriteLine(x)); 
    } 


    public static Expression<Func<TEntity, TValue>> BuildLambda<TEntity, TValue>(string property) where TEntity : class 
     { 
      var param = Expression.Parameter(typeof (TEntity), "e"); 
      var prop = Expression.PropertyOrField(param, property); 
      return Expression.Lambda<Func<TEntity, TValue>>(prop, param); 
     } 
} 

public class Parent { 

    public List<Child> Children { get; set; } 
} 

public class Child { } 

} 
Verwandte Themen