public Func <TTarget, TSource, TTarget> GetMapperFunc() { ValidateMapping(); var targetParam = Expression.Parameter(typeof(TTarget)); var sourceParam = Expression.Parameter(typeof(TSource)); var setterActions = TargetValues.OrderBy(x => x.PropertyName) .Zip(SourceValues.OrderBy(x => x.PropertyName), (tgt, src) => tgt.CreateSetter(src.CreateGetter())) .Concat(CustomMappings) .Select(x => EnsureReturnsTarget(x)) .ToArray() ; if (!setterActions.Any()) { return((tgt, src) => tgt); } var accumulatedLambda = Expression.Invoke(setterActions.First(), targetParam, sourceParam); foreach (var setterExpr in setterActions.Skip(1)) { accumulatedLambda = Expression.Invoke(setterExpr, accumulatedLambda, sourceParam); } var mapperFunc = Expression.Lambda <Func <TTarget, TSource, TTarget> >(accumulatedLambda, targetParam, sourceParam); return(mapperFunc.Compile()); }
private void ValidateMapping() { var targetNames = TargetValues.Select(x => x.PropertyName); var sourceNames = SourceValues.Select(x => x.PropertyName); var unmatchedTargets = targetNames.Except(sourceNames); foreach (var targetProperty in GetUnmappedTargetValues()) { ThrowUnmatchedTarget(targetProperty); } var unmatchedSources = sourceNames.Except(targetNames); foreach (var sourceProperty in unmatchedSources) { ThrowUnmatchedSource(SourceValues.First(x => x.PropertyName == sourceProperty)); } var mismatchedTypes = SourceValues.OrderBy(x => x.PropertyName) .Zip(TargetValues.OrderBy(x => x.PropertyName), (src, tgt) => new { src, tgt }) .Where(x => !x.tgt.ValueType.IsAssignableFrom(x.src.ValueType)); foreach (var mismatch in mismatchedTypes) { var msg = string.Format( "Cannot map [{0}] from [{1}].", mismatch.tgt.Description, mismatch.src.Description ); throw new Exception(msg); } }