using System.Linq.Expressions;
using System.Collections.Generic;
public int SourceNumber { get; set; }
public int TargetNumber { get; set; }
public int SourceNumber { get; set; }
public string SourceName { get; set; }
public static class Binder
public static Binder<T, U> Bind<T, U>(T source, U target)
return new Binder<T, U>();
public static Binder<T, U> Bind<T, U>()
return new Binder<T, U>();
public interface IBindMap<T,U>
void Apply(T source, U target);
void Apply(U source, T target);
public class BindMap<T,U,CP> : IBindMap<T,U>
public Expression<Func<T,CP>> SourceProp { get; set; }
public Expression<Func<U,CP>> TargetProp { get; set; }
public BindMap(Expression<Func<T,CP>> sourceProp, Expression<Func<U,CP>> targetProp) {
public void Apply(T source, U target)
var sourceParam = Expression.Parameter(typeof(T));
var sourceL = Expression.Invoke(SourceProp, sourceParam);
var assignParam = TargetProp.Parameters.First();
var assignTarget = Expression.Assign(TargetProp.Body, sourceL);
var applyL = Expression.Lambda<Action<T, U>>(assignTarget, sourceParam, assignParam);
applyL.Compile()(source, target);
public void Apply(U source, T target)
var sourceParam = Expression.Parameter(typeof(U));
var sourceL = Expression.Invoke(TargetProp, sourceParam);
var assignParam = SourceProp.Parameters.First();
var assignTarget = Expression.Assign(SourceProp.Body, sourceL);
var applyL = Expression.Lambda<Action<U, T>>(assignTarget, sourceParam, assignParam);
applyL.Compile()(source, target);
List<IBindMap<T, U>> bindings { get; set; }
public Binder<T, U> Map<CP>(Expression<Func<T,CP>> sourceProp, Expression<Func<U,CP>> targetProp)
bindings = new List<IBindMap<T,U>>();
bindings.Add(new BindMap<T, U, CP>(sourceProp, targetProp));
public void Apply(T source, U target)
foreach (var binding in bindings)
binding.Apply(source, target);
public void Apply(U source, T target)
foreach (var binding in bindings)
binding.Apply(source, target);
public static void Main()
var sourceTargetBinder = Binder.Bind<SourceClass, TargetClass>()
.Map(sc => sc.SourceNumber, tc => tc.SourceNumber)
.Map(sc => sc.Name, tc => tc.SourceName);
var source = new SourceClass() { SourceNumber = 42, Name = "FourtyTwo" };
var target = new TargetClass();
sourceTargetBinder.Apply(source, target);
target.SourceNumber = 43;
target.SourceName = "FourtyThree";
sourceTargetBinder.Apply(target, source);