C#用AutoMapper创建嵌套对象映射实例

作者:袖梨 2022-06-25

之前在做DTO转换时,用到AutoMapper。但DTO的层次太深了,无奈官方没针对嵌套类型提供好的解决方案,于是自己实现了一下:

思路:采用递归和反射很好的避免手工创建嵌套对象的映射。

第一个版本,已经提交到:https://github.com/AutoMapper/AutoMapper/wiki/Nested-mappings

 代码如下 复制代码
///
    /// 递归创建类型间的映射关系 (Recursively create mappings between types)
    ///created by cqwang
    ///

    ///
    ///
    public static void CreateNestedMappers(Type sourceType, Type destinationType)
    {
        PropertyInfo[] sourceProperties = sourceType.GetProperties(BindingFlags.Public | BindingFlags.Instance);
        PropertyInfo[] destinationProperties = destinationType.GetProperties(BindingFlags.Public | BindingFlags.Instance);
        foreach (var destinationProperty in destinationProperties)
        {
            Type destinationPropertyType = destinationProperty.PropertyType;
            if (Filter(destinationPropertyType))
                continue;

            PropertyInfo sourceProperty = sourceProperties.FirstOrDefault(prop => NameMatches(prop.Name, destinationProperty.Name));
            if (sourceProperty == null)
                continue;

            Type sourcePropertyType=sourceProperty.PropertyType;
            if (destinationPropertyType.IsGenericType)
            {
                Type destinationGenericType = destinationPropertyType.GetGenericArguments()[0];
                if (Filter(destinationGenericType))
                    continue;

                Type sourceGenericType = sourcePropertyType.GetGenericArguments()[0];
                CreateMappers(sourceGenericType, destinationGenericType);
            }
            else
            {
                CreateMappers(sourcePropertyType, destinationPropertyType);
            }
        }

        Mapper.CreateMap(sourceType, destinationType);
    }

    ///
    /// 过滤 (Filter)
    ///

    ///
    ///
    static bool Filter(Type type)
    {
        return type.IsPrimitive || NoPrimitiveTypes.Contains(type.Name);
    }

    static readonly HashSet NoPrimitiveTypes = new HashSet() { "String", "DateTime", "Decimal" };

    private static bool NameMatches(string memberName, string nameToMatch)
    {
        return String.Compare(memberName, nameToMatch, StringComparison.OrdinalIgnoreCase) == 0;
    }




后来自测中发现,要过滤的一些结构体可能很多,比较麻烦,所以自己又完善了下,有了第二个版本

第二个版本在公司内的一些服务中已经使用并上线,挺好。因为并未涉及到公司内的任何业务信息,只是简单的思路和实现,所以这里贴出来给大家分享一下。

相关文章

精彩推荐