private static object MapTypes(Type sourceType, Type targetType, PropertyMapInfo[] propertyMapInfos, IMapperConfigurationExpression mapperConfiguration) { var createMapMethodInfo = GenericCreateMap.MakeGenericMethod(sourceType, targetType); //actually create the mapping var mapObject = createMapMethodInfo.Invoke(mapperConfiguration, new object[] { }); Debug.WriteLine($"Mapping created for source type {sourceType.Name} to target type {targetType.Name}"); var mapObjectExpression = Expression.Constant(mapObject); var sourceTypeParameter = Expression.Parameter(sourceType); foreach (var propMapInfo in propertyMapInfos) { var sourcePropertyInfos = propMapInfo.SourcePropertyInfos; var targetPropertyInfo = propMapInfo.TargetPropertyInfo; var targetPropertyName = targetPropertyInfo.Name; Debug.WriteLine($"-- Mapping property {string.Join(".", sourcePropertyInfos.Select(s => s.Name))} to target type {targetPropertyName}"); var finalSourcePropertyType = sourcePropertyInfos.Last().PropertyType; var memberConfigType = typeof(IMemberConfigurationExpression <, ,>) .MakeGenericType(sourceType, targetType, typeof(object)); var memberConfigTypeParameter = Expression.Parameter(memberConfigType); var propertyExpression = sourcePropertyInfos.Aggregate <PropertyInfo, Expression>(null, (current, prop) => current == null ? Expression.Property(sourceTypeParameter, prop) : Expression.Property(current, prop)); var memberOptions = Expression.Call(memberConfigTypeParameter, nameof(IMemberConfigurationExpression.MapFrom), new Type[] { finalSourcePropertyType }, Expression.Lambda( propertyExpression, sourceTypeParameter )); var lambdaExpression = Expression.Lambda(memberOptions, memberConfigTypeParameter); var forMemberMethodExpression = Expression.Call( mapObjectExpression, nameof(IMappingExpression <object, object> .ForMember), Type.EmptyTypes, Expression.Constant(targetPropertyInfo.Name), lambdaExpression); //TODO: cache this somewhere for better repeat performance Expression.Lambda(forMemberMethodExpression).Compile().DynamicInvoke(); } return(mapObject); }
internal static object MapTypes(Type sourceType, Type targetType, PropertyMapInfo[] propertyMapInfos, IMapperConfigurationExpression mapperConfiguration) { var createMapMethodInfo = GenericCreateMap.MakeGenericMethod(sourceType, targetType); //actually create the mapping var mappingExpression = createMapMethodInfo.Invoke(mapperConfiguration, new object[] { }); Debug.WriteLine($"Mapping created for source type {sourceType.Name} to target type {targetType.Name}"); var mapObjectExpression = MapProperties(sourceType, targetType, propertyMapInfos, mappingExpression); Expression.Lambda(mapObjectExpression).Compile().DynamicInvoke(); return(mappingExpression); }