I have a generic class with a lambda property defined as such:
public class Transformation<TProperty> : TransformationBase
{
public Func<TProperty, TProperty> Transform { get; private set; }
...
I'm trying to compile an Action that can call this Transform property (on a property of Foo). I don't know TProperty at compile-time. I've started with this:
private static Action<Foo> Compile(Transformation transformation)
{
var fooParameter = Expression.Parameter(typeof(Foo));
var changePropertyValue = Expression.Constant(transformation);
var transformProperty = Expression.Property(changePropertyValue, "Transform");
var transfromCall = Expression.Call(transformProperty, ?
}
How can I call/execute the transformProperty?
EDIT: Foo (which is known a compile time) has an untyped property Value which needs to be transformed using the Transform property of the Transformation:
public class Foo {
public object Value { get; set; }
}
So, hand-written as an example where TProperty is string it would be:
Foo foo = ... // coming from an external source
Transformation<string> tranformation = ... // coming from an external source
foo.Value = transformation.Transform((string)foo.Value);
Except that I don't know the exact type of the Transformation as it is defined in an external assembly. So, instead of string it could be int or something else. That's why I want to use Expression Trees to compile an Action for a given transformation, such that I can call:
Foo foo = ... // coming from an external source
TransformationBase transformation = ... // coming from an external source
Action<Foo> transform = Compile(transformation);
transform(foo); // should transform foo.Value using the Transform property of 'transformation'
Note: I made Transformation inherit from TransformationBase to clarify this discussion.
Your problems relate more to the lack of typing around your problem.
Foo.Value
is loosely typed, but your transform functions are strongly typed. Expression Trees are also strongly typed. Using them doesn't allow you to magically call code in a loosely typed manner.The solution is either a lot of reflection, or some easy dynamic:
EDIT: I added CompileUntyped which uses ExpressionTrees.I also added CompileReflection, which uses Reflection without ExpressionTrees. I would recommend the one that uses dynamic. It is by far the easiest to read, hence the easiest to maintain.