C# AutoMapper 动态映射 嵌套对象映射 嵌套集合映射

AutoMapper支持Dynamic 映射,Dynamic Deep 映射.

代码:

using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.Dynamic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using AutoMapper;
using Newtonsoft.Json;

namespace ConsoleApp1
{
    class SubSetting
    {
        public int SubTimeout { get; set; }
        public string SubColour { get; set; }
    }

    class Settings
    {
        public int Timeout { get; set; }
        public string Colour { get; set; }
        public SubSetting SubSettings { get; set; }

        public List<SubSetting> SubSettingList { get; set; }
    }

    public static class DynamicExtensions
    {
        public static dynamic ToDynamic(this object value)
        {
            IDictionary<string, object> expando = new ExpandoObject();
            foreach (PropertyDescriptor property in TypeDescriptor.GetProperties(value.GetType()))
            {
                object val = property.GetValue(value);
                if ((property.PropertyType.IsGenericType || property.PropertyType.Name.Contains("[]")) && val is IEnumerable<object>)
                {
                    var values = val as IEnumerable<object>;
                    List<ExpandoObject> result = new List<ExpandoObject>();
                    foreach (var v in values)
                    {
                        result.Add(v.ToDynamic());
                    }
                    expando.Add(property.Name, result);
                }
                else if (property.PropertyType.Name.Contains("Anonymous"))
                {
                    expando.Add(property.Name, val.ToDynamic());
                }
                else
                {
                    expando.Add(property.Name, val);
                }
            }
            return expando as ExpandoObject;
        }
    }

    class Program
    {
        static void Main(string[] args)
        {
            dynamic baseSettings = new ExpandoObject();
            baseSettings.Timeout = 1;
            baseSettings.Colour = "Red";
            baseSettings.SubSettings = new ExpandoObject();
            baseSettings.SubSettings.SubTimeout = 11;
            baseSettings.SubSettings.SubColour = "Green";

            baseSettings.SubSettingList = new List<ExpandoObject>();

            dynamic SubSettings1 = new ExpandoObject();
            SubSettings1.SubTimeout = 15;
            SubSettings1.SubColour = "big1";
            dynamic SubSettings2= new ExpandoObject();
            SubSettings2.SubTimeout = 16;
            SubSettings2.SubColour = "big2";

            (baseSettings.SubSettingList as List<ExpandoObject>).Add(SubSettings1);
            (baseSettings.SubSettingList as List<ExpandoObject>).Add(SubSettings2);

            //改写
            dynamic overrideSettings = new ExpandoObject();
            overrideSettings.Timeout = 2;
            overrideSettings.SubSettings = new ExpandoObject();
            overrideSettings.SubSettings.SubTimeout = 99;

            var config = new MapperConfiguration(cfg =>
            {
            });
            var mapper = config.CreateMapper();
            var settings = mapper.Map<Settings>(baseSettings);
            Console.WriteLine(JsonConvert.SerializeObject(settings));
            mapper.Map(overrideSettings, settings);
            Console.WriteLine(JsonConvert.SerializeObject(settings));

            var anonymousData = new
            {
                SubSettingList = new Collection<dynamic> // 或者 new [] , new List<dynamic> 都可以
                {
                    new {SubTimeout=95,
                        SubColour="bbz1"},
                    new {SubTimeout=96,
                        SubColour="bbz2"}
                },
                Timeout =88,
                Colour="bb",
                SubSettings = new
                {
                    SubTimeout = 89,
                    SubColour = "bbSub"
                }
            };
            var d2 = anonymousData.ToDynamic();
            var settings2 = mapper.Map<Settings>(d2);
            Console.WriteLine(JsonConvert.SerializeObject(settings2));
            Console.ReadKey();
        }
    }
}

演示代码中包含了嵌套类,嵌套集合类.

匿名嵌套,匿名集合嵌套.

对于anonymous的匿名类,直接使用AutoMapper映射会报错,这里使用了匿名类转ExpandoObject来保证AutoMapper的稳定运行.

在扩展方法ToDynamic中,适配了嵌套对象,嵌套集合对象的转换.保证子类集合可以正常使用.

此Demo可以运用到数据动态同步.可选字段的同步

原文地址:https://www.cnblogs.com/Raspberry-zx/p/12157103.html