Sebastian
Sebastian

Reputation: 972

Create Expression Tree dynamically

I had an idea and want to know if it can work. I have a simple classes with properties and want to generate accessors with Expressions. But in the end I need to get a Func<Test, string> but I don't know the types when I use them. A small example

class Program
{
    static void Main(string[] args)
    {
        Test test = new Test();
        test.TestString = "Blubb";
        var actionStub = typeof(Helper).GetMethod("CreatePropertyGetter").MakeGenericMethod(new Type[] { test.GetType(), typeof(string)});
        dynamic action = actionStub.Invoke(null, new object[] {test.GetType(), "TestString"});

        var x = action(test);
    }
}

public class Test
{
    public string TestString { get; set; }
}

public static class Helper
{
    public static Func<TType, TPropValueType> CreatePropertyGetter<TType, TPropValueType>(Type type,
                                                                                  string propertyName)
    {
        PropertyInfo fieldInfo = type.GetProperty(propertyName);
        ParameterExpression targetExp = Expression.Parameter(typeof(TType), "target");

        MemberExpression fieldExp = Expression.Property(targetExp, fieldInfo);
        UnaryExpression assignExp = Expression.Convert(fieldExp, typeof(TPropValueType));

        Func<TType, TPropValueType> getter =
            Expression.Lambda<Func<TType, TPropValueType>>(assignExp, targetExp).Compile();

        return getter;
    }
}

The problem is I cant call the expression without dynamic, because I cant simple cast it to Func<object, object>

Upvotes: 0

Views: 99

Answers (2)

Serge Semenov
Serge Semenov

Reputation: 10052

It's not clear what exactly you are asking for, but here is an example how you can make it Func<object, object>:

public static class Helper
{
    public static Func<object, object> CreatePropertyGetter(Type type, string propertyName)
    {
        var fieldInfo = type.GetProperty(propertyName);
        var targetExp = Expression.Parameter(typeof(object), "target");
        var fieldExp = Expression.Property(Expression.ConvertChecked(targetExp, type), fieldInfo);
        var getter = Expression.Lambda<Func<object, object>>(fieldExp,targetExp).Compile();
        return getter;
    }
}

Upvotes: 0

usr
usr

Reputation: 171246

You're generating (TType target) => target.Something. Instead, generate (object target) => (object)((TType)target).Something so that you can use Func<object, object>.

Upvotes: 2

Related Questions