在运行时使用PropertyInfo排除泛型函数

本文关键字:排除 泛型 函数 PropertyInfo 运行时 | 更新日期: 2023-09-27 18:18:24

我有以下功能:

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

我正在玩反射:

如何在运行时使用动态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); 
....
}

在运行时使用PropertyInfo排除泛型函数

这是真的很难理解什么可能是你的问题,如果我没有猜对请提供可运行的代码样本使用。net Fiddle或类似的网站:

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