0

lI have the following function:

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

I am playing around with reflections:

How can exclude this function at runtime with a dynamic TEntity and TValue. Is it even possible?

Example:

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

....
}
Valter
  • 2,859
  • 5
  • 30
  • 51
  • There you may find enlightenment: http://stackoverflow.com/questions/232535/how-do-i-use-reflection-to-call-a-generic-method – csharpfolk Nov 17 '16 at 21:02
  • @csharpfolk The only problem with the link you provide is when invoke the function, it always return an object not Expression>. What i am doing after this invoke this function, it throws an error because the type is object not Expression>. Even it I try to convert with Convert.ChangeType i have the same issue with returning an object instead of Expression>. – Valter Nov 18 '16 at 14:37

1 Answers1

0

It was really hard to understand what may be your problem, if I didn't guess right please provide runnable code sample using .NET Fiddle or similar site:

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

}
csharpfolk
  • 4,124
  • 25
  • 31