2016-11-17 59 views
0

李有以下功能在運行時排除通用功能使用的PropertyInfo

如何在運行時可以排除這種功能與動態TEntity和TValue。它甚至有可能嗎?

例子:

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

在那裏你可以找到啓示:http://stackoverflow.com/questions/232535/how-do-i-use-reflection-to-call-a-generic-method – csharpfolk

+0

@csharpfolk你提供的鏈接唯一的問題是當調用函數時,它總是返回一個不是Expression >的對象。在調用這個函數之後,我在做什麼,它會拋出一個錯誤,因爲類型是object而不是Expression >。即使它我嘗試轉換Convert.ChangeType我有同樣的問題返回一個對象,而不是表達式>。 – Valter

回答

0

這真的很難理解什麼可能是你的問題,如果我沒猜錯的權利,請提供使用.NET小提琴或類似的網站可運行的代碼示例:

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

}