两个对象属性值映射 之 反射赋值

MapToAttribute类:
using System;
namespace Test
{
    public class MapToAttribute : Attribute
    {
        public string Name { get; set; }
    }
    public class NotMapToAttribute : Attribute
    {
    }
}

DataExtend类:

using System;

using System.Collections.Generic;

using System.ComponentModel;

using System.Data;

using System.Linq;

using System.Reflection;

namespace Test

{

    public static class DataExtend

    {

        /// <summary>

        /// 两个类实例拷贝(可配合MapTo、NotMapTo特性使用)

        /// </summary>

        /// <typeparam name="T">目标类型</typeparam>

        /// <param name="obj">被拷贝的类实例</param>

        /// <param name="IsIgnoreNull">是否忽略空值(被拷贝的属性值为空时则不拷贝该属性值)</param>

        /// <returns>返回一个新的目标类型实例</returns>

        public static T MapTo<T>(this object obj, bool IsIgnoreNull = false)

        {

            if (obj == null)

            {

                return default(T);

            }

            object new_obj = Activator.CreateInstance(typeof(T));

            PropertyInfo[] old_Properties = obj.GetType().GetProperties();

            List<PropertyInfo> new_Properties = typeof(T).GetProperties().Where(p => p.GetCustomAttribute(typeof(NotMapToAttribute)) == null).ToList();

            foreach (PropertyInfo propertyInfo in new_Properties)

            {

                if (propertyInfo.SetMethod != null)

                {

                    object value = null;

                    Attribute attribute = propertyInfo.GetCustomAttribute(typeof(MapToAttribute));

                    if (attribute != null)

                    {

                        string mapToAttributeName = ((MapToAttribute)attribute).Name;

                        if (old_Properties.Any(p => p.Name == mapToAttributeName))

                        {

                            value = obj.GetType().GetProperty(mapToAttributeName).GetValue(obj);

                            SetValue(propertyInfo, new_obj, value, IsIgnoreNull);

                        }

                    }

                    else if (old_Properties.Any(p => p.Name == propertyInfo.Name))

                    {

                        value = obj.GetType().GetProperty(propertyInfo.Name).GetValue(obj);

                        SetValue(propertyInfo, new_obj, value, IsIgnoreNull);

                    }

                }

            }

            return (T)new_obj;

        }

        /// <summary>

        /// 两个类实例拷贝(可配合MapTo、NotMapTo特性使用)

        /// </summary>

        /// <typeparam name="T">目标类型</typeparam>

        /// <param name="old_obj">被拷贝的类实例</param>

        /// <param name="new_obj">目标类实例</param>

        /// <param name="IsIgnoreNull">是否忽略空值(被拷贝的属性值为空时则不拷贝该属性值)</param>

        /// <returns>返回目标类实例</returns>

        public static T MapTo<T>(this object old_obj, T new_obj, bool IsIgnoreNull = false)

        {

            if (old_obj == null)

            {

                return new_obj;

            }

            PropertyInfo[] old_Properties = old_obj.GetType().GetProperties();

            List<PropertyInfo> new_Properties = typeof(T).GetProperties().Where(p => p.GetCustomAttribute(typeof(NotMapToAttribute)) == null).ToList();

            foreach (PropertyInfo propertyInfo in new_Properties)

            {

                if (propertyInfo.SetMethod != null)

                {

                    object value = null;

                    Attribute attribute = propertyInfo.GetCustomAttribute(typeof(MapToAttribute));

                    if (attribute != null)

                    {

                        string mapToAttributeName = ((MapToAttribute)attribute).Name;

                        if (old_Properties.Any(p => p.Name == mapToAttributeName))

                        {

                            value = old_obj.GetType().GetProperty(mapToAttributeName).GetValue(old_obj);

                            SetValue(propertyInfo, new_obj, value, IsIgnoreNull);

                        }

                    }

                    else if (old_Properties.Any(p => p.Name == propertyInfo.Name))

                    {

                        value = old_obj.GetType().GetProperty(propertyInfo.Name).GetValue(old_obj);

                        SetValue(propertyInfo, new_obj, value, IsIgnoreNull);

                    }

                }

            }

            return new_obj;

        }

        private static void SetValue(PropertyInfo propertyInfo, object new_obj, object value, bool IsIgnoreNull)

        {

            if (IsIgnoreNull)

            {

                if (value != null)

                {

                    propertyInfo.SetValue(new_obj, HackType(value, propertyInfo.PropertyType));

                }

            }

            else

            {

                propertyInfo.SetValue(new_obj, HackType(value, propertyInfo.PropertyType));

            }

        }

        /// <summary>

        /// 将对象转换为指定类型

        /// </summary>

        /// <param name="value">待转换对象</param>

        /// <param name="conversionType">目标类型</param>

        /// <returns></returns>

        public static object HackType(object value, Type conversionType)

        {

            try

            {

                if (conversionType.IsGenericType && conversionType.GetGenericTypeDefinition().Equals(typeof(Nullable<>)))

                {

                    if (value == null)

                    {

                        return null;

                    }

                    NullableConverter converter = new NullableConverter(conversionType);

                    conversionType = converter.UnderlyingType;

                }

                return Convert.ChangeType(value, conversionType);

            }

            catch (Exception ex)

            {

                return conversionType.IsValueType ? Activator.CreateInstance(conversionType) : null;

            }

        }

        public static List<T> ToList<T>(this DataTable dt) where T : new()

        {

            List<string> listTableColumn = new List<string>();

            for (int i = 0; i < dt.Columns.Count; i++)

            {

                listTableColumn.Add(dt.Columns[i].ColumnName.ToLower());

            }

            List<T> list = new List<T>();

            PropertyInfo[] properties = typeof(T).GetProperties(BindingFlags.GetProperty | BindingFlags.Public | BindingFlags.Instance);

            foreach (DataRow dr in dt.Rows)

            {

                T local = Activator.CreateInstance<T>();

                foreach (PropertyInfo info in properties)

                {

                    if (listTableColumn.Contains(info.Name.ToLower()) && !(((dr[info.Name] is DBNull) || string.IsNullOrEmpty(dr[info.Name].ToString()))))//表拥有此列,且有值时

                    {

                        info.SetValue(local, HackType(dr[info.Name], info.PropertyType), null);

                    }

                }

                list.Add(local);

            }

            return list;

        }

    }

}

DbModel类:
namespace Test
{
    public class DbModel
    {
        [MapTo(Name = "Field1_ViewModel")]
        public string Field1 { get; set; }
        [MapTo(Name = "Field2_ViewModel")]
        public string Field2 { get; set; }
        //[IgnoreDataMember]
        public string Field3 { get; set; }
        public string Field4 { get; set; }
        [NotMapTo]
        public string Field5 { get; set; }
        public string Field6 { get; set; }
    }
}
ViewModel类:
namespace Test
{
    public class ViewModel
    {
        public string Field1_ViewModel { get; set; }
        public string Field2_ViewModel { get; set; }
        public string Field3 { get; set; }
        public string Field4_ViewModel { get; set; }
        public string Field5 { get; set; }
        public string Field6 { get; set; }
    }
}
测试:
static void Main(string[] args)
{
    DbModel dbModel = new DbModel();
    dbModel.Field4 = "4";
    dbModel.Field6 = "6";
    ViewModel viewModel = new ViewModel();
    viewModel.Field1_ViewModel = "1";
    viewModel.Field2_ViewModel = "2";
    viewModel.Field3 = "3";
    viewModel.Field4_ViewModel = "4";
    viewModel.Field5 = "5";
    viewModel.Field6 = null;
    //会创建新对象
    dbModel = viewModel.MapTo<DbModel>(true);
    //不会创建新对象
    //dbModel = viewModel.MapTo(dbModel,true);
    string str = Newtonsoft.Json.JsonConvert.SerializeObject(dbModel);
}