示例#1
0
        public static void ResolveDtoMaps(this IMapperConfigurationExpression mapper)
        {
            var types = GetAllDtos();

            foreach (var type in types)
            {
                var dto        = Activator.CreateInstance(type);
                var interfaces = type.GetInterfaces().Where(t2 => t2.IsGenericType && t2.GetGenericTypeDefinition() == typeof(IDto <,>));
                foreach (var @interface in interfaces)
                {
                    var genericBackArguments = @interface.GetGenericArguments();
                    var genericArguments     = genericBackArguments.Reverse().ToArray();
                    if (genericArguments.Length < 2)
                    {
                        continue;
                    }

                    var createMaps = mapper.GetType().GetMethods().First(t => t.Name == "CreateMap" && t.IsGenericMethod);
                    var map        = createMaps.MakeGenericMethod(genericArguments).Invoke(mapper, null);
                    var mapConfig  = Activator.CreateInstance(typeof(Maps <,>).MakeGenericType(genericBackArguments), map);
                    type.GetMethod(nameof(IDto <object, object> .MapExpandables)).Invoke(dto, new[] { mapConfig });
                    type.GetMethod(nameof(IDto <object, object> .Map)).Invoke(dto, new[] { mapConfig });


                    var mapBack       = createMaps.MakeGenericMethod(genericBackArguments).Invoke(mapper, null);
                    var mapBackConfig = Activator.CreateInstance(typeof(Maps <,>).MakeGenericType(genericArguments), mapBack);
                    type.GetMethod(nameof(IDto <object, object> .MapBack)).Invoke(dto, new[] { mapBackConfig });
                }
            }
        }
示例#2
0
        public static void CreateAutoAttributeMaps(this IMapperConfigurationExpression configuration, Type type, Type[] targetTypes, MemberList memberList)
        {
            //获取源中具有automapkeyattribute的所有属性
            var sourceKeysPropertyInfo = type.GetProperties()
                                         .Where(w => w.GetCustomAttribute <AutoMapKeyAttribute>() != null)
                                         .Select(s => s).ToList();

            foreach (var targetType in targetTypes)
            {
                if (!sourceKeysPropertyInfo.Any())
                {
                    configuration.CreateMap(type, targetType, memberList);
                    continue;
                }

                BinaryExpression equalityComparer = null;

                //在lambda表达式中表示源示例:(source)=>…
                ParameterExpression sourceParameterExpression = Expression.Parameter(type, "source");
                //在lambda表达式中表示目标示例:(target)=>…
                ParameterExpression targetParameterExpression = Expression.Parameter(targetType, "target");


                //我们可以使用多个automapkey来比较
                foreach (PropertyInfo propertyInfo in sourceKeysPropertyInfo)
                {
                    //在lambda表达式中表示参数的特定属性示例:(source)=>source.id
                    MemberExpression sourcePropertyExpression = Expression.Property(sourceParameterExpression, propertyInfo);

                    //为目标查找与之比较的同名属性
                    //例如,如果我们在源代码中有属性id上的attribut automapkey,那么我们希望在目标中获取要比较的id,而不是
                    var targetPropertyInfo = targetType.GetProperty(sourcePropertyExpression.Member.Name);

                    //如果目标中不存在automapkeyattribute为的属性,则会发生这种情况
                    if (targetPropertyInfo is null)
                    {
                        continue;
                    }

                    //在lambda表达式中,表示参数的特定属性示例:(target)=>target.id
                    MemberExpression targetPropertyExpression = Expression.Property(targetParameterExpression, targetPropertyInfo);

                    //比较源中automapkey定义的属性与目标中的属性不同
                    //示例(source,target)=>source.id==target.id
                    BinaryExpression equal = Expression.Equal(sourcePropertyExpression, targetPropertyExpression);

                    if (equalityComparer is null)
                    {
                        equalityComparer = equal;
                    }
                    else
                    {
                        //如果我们比较多个键,我们要在
                        //Exemple : (source, target) => source.Email == target.Email && source.UserName == target.UserName
                        equalityComparer = Expression.And(equalityComparer, equal);
                    }
                }

                //如果目标中没有匹配的automapkey
                //在这种情况下,我们添加默认映射
                if (equalityComparer is null)
                {
                    configuration.CreateMap(type, targetType, memberList);
                    continue;
                }

                //我们需要使func<sourcetype,targettype,bool>的泛型类型来调用后面的expression.lambda
                var funcGenericType = typeof(Func <, ,>).MakeGenericType(type, targetType, typeof(bool));

                //生成表达式的方法信息。lambda<func<sourceType,targetType,bool>>稍后调用
                var lambdaMethodInfo = typeof(Expression).GetMethod("Lambda", 2, 1).MakeGenericMethod(funcGenericType);

                //调用expression.lambda
                var expressionLambdaResult = lambdaMethodInfo.Invoke(null, new object[] { equalityComparer, new ParameterExpression[] { sourceParameterExpression, targetParameterExpression } });

                //获取imapperConfigurationExpression.createMap<source,target>
                var createMapMethodInfo = configuration.GetType().GetMethod("CreateMap", 1, 2).MakeGenericMethod(type, targetType);

                //调用configuration.createmap<source,target>()。
                var createMapResult = createMapMethodInfo.Invoke(configuration, new object[] { memberList });

                var autoMapperCollectionAssembly = Assembly.Load("AutoMapper.Collection");

                var autoMapperCollectionTypes = autoMapperCollectionAssembly.GetTypes();

                var equalityComparisonGenericMethodInfo = autoMapperCollectionTypes
                                                          .Where(w => !w.IsGenericType && !w.IsNested)
                                                          .SelectMany(s => s.GetMethods()).Where(w => w.Name == "EqualityComparison")
                                                          .FirstOrDefault()
                                                          .MakeGenericMethod(type, targetType);

                //调用EqualityComparison
                //Exemple configuration.CreateMap<Source, Target>().EqualityComparison((source, target) => source.Id == target.Id)
                equalityComparisonGenericMethodInfo.Invoke(createMapResult, new object[] { createMapResult, expressionLambdaResult });
            }
        }
示例#3
0
        /// <summary>
        /// 创建映射
        /// </summary>
        /// <param name="configuration"></param>
        /// <param name="type">原始类</param>
        /// <param name="targetTypes">目标类列表</param>
        /// <param name="memberList">成员类型,是Source还是Destination,用来验证字段已经全部映射完毕</param>
        public static void CreateAutoAttributeMaps(this IMapperConfigurationExpression configuration, Type type, Type[] targetTypes, MemberList memberList)
        {
            //Get all the properties in the source that have the AutoMapKeyAttribute
            var sourceKeysPropertyInfo = type.GetProperties()
                                         .Where(w => w.GetCustomAttribute <AutoMapKeyAttribute>() != null)
                                         .Select(s => s).ToList();

            foreach (var targetType in targetTypes)
            {
                //这里表示,当前类打了自动映射的标签,且类里面的字段都没有打映射主键标签,那么当前类就直接进行映射
                if (!sourceKeysPropertyInfo.Any())
                {
                    configuration.CreateMap(type, targetType, memberList);
                    continue;
                }

                BinaryExpression equalityComparer = null;

                //In a lambda expression represent the source example : (source) => ...
                ParameterExpression sourceParameterExpression = Expression.Parameter(type, "source");
                //In a lambda expression represent the target example : (target) => ...
                ParameterExpression targetParameterExpression = Expression.Parameter(targetType, "target");


                //We could use multiple AutoMapKey to compare the determine equality
                //遍历那些打了自动映射键的字段,根据属性的键进行匹配,匹配上了的才进行赋值
                foreach (PropertyInfo propertyInfo in sourceKeysPropertyInfo)
                {
                    //In a lambda expression represent a specific property of a parameter example : (source) => source.Id
                    MemberExpression sourcePropertyExpression = Expression.Property(sourceParameterExpression, propertyInfo);

                    //Find the target a property with the same name to compare with
                    //Example if we have in source the attribute AutoMapKey on the Property Id we want to get Id in the target to compare against
                    var targetPropertyInfo = targetType.GetProperty(sourcePropertyExpression.Member.Name);

                    //It happen if the property with AutoMapKeyAttribute does not exist in target
                    if (targetPropertyInfo is null)
                    {
                        continue;
                    }

                    //In a lambda expression represent a specific property of a parameter example : (target) => target.Id
                    MemberExpression targetPropertyExpression = Expression.Property(targetParameterExpression, targetPropertyInfo);

                    //Compare the property defined by AutoMapKey in the source against the same property in the target
                    //Example (source, target) => source.Id == target.Id
                    BinaryExpression equal = Expression.Equal(sourcePropertyExpression, targetPropertyExpression);

                    if (equalityComparer is null)
                    {
                        equalityComparer = equal;
                    }
                    else
                    {
                        //If we compare multiple key we want to make an and condition between
                        //Example : (source, target) => source.Email == target.Email && source.UserName == target.UserName
                        equalityComparer = Expression.And(equalityComparer, equal);
                    }
                }

                //If there is not match for AutoMapKey in the target
                //In this case we add the default mapping
                if (equalityComparer is null)
                {
                    configuration.CreateMap(type, targetType, memberList);
                    continue;
                }

                //We need to make a generic type of Func<SourceType, TargetType, bool> to invoke later Expression.Lambda
                var funcGenericType = typeof(Func <, ,>).MakeGenericType(type, targetType, typeof(bool));

                //Make a method info of Expression.Lambda<Func<SourceType, TargetType, bool>> to call later
                var lambdaMethodInfo = typeof(Expression).GetMethod("Lambda", 2, 1).MakeGenericMethod(funcGenericType);

                //Make the call to Expression.Lambda
                var expressionLambdaResult = lambdaMethodInfo.Invoke(null, new object[] { equalityComparer, new ParameterExpression[] { sourceParameterExpression, targetParameterExpression } });

                //Get the method info of IMapperConfigurationExpression.CreateMap<Source, Target>
                var createMapMethodInfo = configuration.GetType().GetMethod("CreateMap", 1, 2).MakeGenericMethod(type, targetType);

                //Make the call to configuration.CreateMap<Source, Target>().
                var createMapResult = createMapMethodInfo.Invoke(configuration, new object[] { memberList });

                var autoMapperCollectionAssembly = Assembly.Load("AutoMapper.Collection");

                var autoMapperCollectionTypes = autoMapperCollectionAssembly.GetTypes();

                var equalityComparisonGenericMethodInfo = autoMapperCollectionTypes
                                                          .Where(w => !w.IsGenericType && !w.IsNested)
                                                          .SelectMany(s => s.GetMethods()).Where(w => w.Name == "EqualityComparison")
                                                          .FirstOrDefault()
                                                          .MakeGenericMethod(type, targetType);

                //Make the call to EqualityComparison
                //Exemple configuration.CreateMap<Source, Target>().EqualityComparison((source, target) => source.Id == target.Id)
                equalityComparisonGenericMethodInfo.Invoke(createMapResult, new object[] { createMapResult, expressionLambdaResult });
            }
        }