This is a learning exercise in expression trees.
I have this working code:
class Foo
{
public int A { get; set; }
public string B { get; set; }
}
class Bar
{
public int C { get; set;}
public string D { get; set; }
}
class FieldMap
{
public PropertyInfo From { get; set; }
public PropertyInfo To { get; set; }
}
class Program
{
static Action<TFrom, TTo> CreateMapper<TFrom, TTo>(IEnumerable<FieldMap> fields)
{
ParameterExpression fromParm = Expression.Parameter(typeof(TFrom), "from");
ParameterExpression toParm = Expression.Parameter(typeof(TTo), "to");
//var test = new Func<string, string>(x => x);
//var conversionExpression = Expression.Call(null, test.Method);
var assignments = from fm in fields
let fromProp = Expression.Property(fromParm, fm.From)
let toProp = Expression.Property(toParm, fm.To)
select Expression.Assign(toProp, fromProp);
var lambda = Expression.Lambda<Action<TFrom, TTo>>(
Expression.Block(assignments),
new ParameterExpression[] { fromParm, toParm });
return lambda.Compile();
}
static void Main(string[] args)
{
var pa = typeof(Foo).GetProperty("A");
var pb = typeof(Foo).GetProperty("B");
var pc = typeof(Bar).GetProperty("C");
var pd = typeof(Bar).GetProperty("D");
var mapper = CreateMapper<Foo, Bar>(new FieldMap[]
{
new FieldMap() { From = pa, To = pc },
new FieldMap() { From = pb, To = pd }
});
Foo f = new Foo();
Bar b = new Bar();
f.A = 20;
f.B = "jason";
b.C = 25;
b.D = "matt";
mapper(f, b); // copies properties from f into b
}
}
Works nicely. As noted it copies the corresponding properties from f to b. Now, supposing I wanted to add some conversion or formatting method that takes the “from property”, does some magic, and then sets the “to property” equal to the result. Note the two commented out lines in the middle of CreateMapper.
How do I accomplish this? I got this far, but I’m sort of lost now.
Your code sample is almost there; you can use
Expression.Callto do the transformation as you are clearly trying to do. Instead of assigningtoPropto thefromPropMemberExpression, you can assign to a MethodCallExpression representing the value of the transformation.The tricky part here is to figure out how to do the transformation, which I assume will vary for different properties.
You can replace the LINQ expression with:
(Notice that the right-hand side of the assignment is now
fromTransformedrather thanfromProp.)where
GetTransformlooks something like (I’ve assumed here that the nature of the transformation depends only on the type of the property):Then the only thing left to do is filling in the transformations themselves; for example:
Then, your usage-test method would produce: