ly188:二話不說上代碼
public static class MappingExtension { #region 對象值映射賦值(屬性名稱根據被指映射) /// <summary> /// 對象值映射賦值(屬性名稱根據被指映射) /// </summary> /// <typeparam name="T">需要賦值的對象:不能為空</typeparam> /// <typeparam name="TA">數據源:不能為空</typeparam> /// <param name="sourceInfo">數據源</param> /// <param name="resInfo">需要賦值的對象</param> public static void MappingTo<T, TA>(this TA sourceInfo, T resInfo) where T : class, new() where TA : class, new() { if (sourceInfo == null || resInfo == null) { return; } Type sourceType = typeof(TA); Type resType = typeof(T); //// 獲取數據源public屬性集合 PropertyInfo[] sourcePropertyInfoList = sourceType.GetProperties(); if (sourcePropertyInfoList != null) { //// 獲取返回的對象的共有屬性的名稱集合,數據源不存在的不需要做賦值 var resProList = resType.GetProperties(); Dictionary<string, PropertyInfo> resNameProDic = new Dictionary<string, PropertyInfo>(); if (resProList != null) { foreach (var item in resProList) { var isIgnore = item.IsDefined(typeof(IgnoreAttribute), false); if (!isIgnore) { string resProName = item.Name; var mappingName = item.GetCustomAttribute<MappingNameAttribute>()?.MappingName; if (string.IsNullOrWhiteSpace(mappingName)) { resNameProDic.Add(resProName, item); } else { resNameProDic.Add(mappingName, item); } } } } //// 給對應(相同)的屬性賦值 foreach (PropertyInfo sourcePropertyInfo in sourcePropertyInfoList) { string sourcePropertyInfoName = sourcePropertyInfo.Name; if (resNameProDic.ContainsKey(sourcePropertyInfoName)) { //// 獲取數據源對應屬性值 object sourceProValue = sourcePropertyInfo.GetValue(sourceInfo, null); //// 給返回的對象相同屬性賦值 FillProValue(resInfo, sourcePropertyInfo, resNameProDic[sourcePropertyInfoName], sourceProValue); } } } } #endregion #region 對象值映射賦值(屬性名稱根據被指映射) /// <summary> /// 對象值映射賦值(屬性名稱根據被指映射) /// </summary> /// <typeparam name="T">需要賦值的對象:不能為空</typeparam> /// <typeparam name="TA">數據源:不能為空</typeparam> /// <param name="sourceList">數據源</param> /// <param name="resInfo">需要賦值的對象</param> public static void MappingToList<T, TA>(this List<TA> sourceList, List<T> resList) where T : class, new() where TA : class, new() { if (sourceList == null || resList == null) { return; } Type sourceType = typeof(TA); Type resType = typeof(T); //// 獲取數據源public屬性集合 PropertyInfo[] sourcePropertyInfoList = sourceType.GetProperties(); if (sourcePropertyInfoList != null) { //// 獲取返回的對象的共有屬性的名稱集合,數據源不存在的不需要做賦值 var resProList = resType.GetProperties(); Dictionary<string, PropertyInfo> resNamePro = new Dictionary<string, PropertyInfo>(); if (resProList != null) { foreach (var item in resProList) { var isIgnore = item.IsDefined(typeof(IgnoreAttribute), false); if (!isIgnore) { string resProName = item.Name; var mappingName = item.GetCustomAttribute<MappingNameAttribute>()?.MappingName; if (string.IsNullOrWhiteSpace(mappingName)) { resNamePro.Add(resProName, item); } else { resNamePro.Add(mappingName, item); } } } } foreach (var sourceInfo in sourceList) { //// 給對應(相同)的屬性賦值 T resInfo = new T(); //// 給對應(相同)的屬性賦值 foreach (PropertyInfo sourcePropertyInfo in sourcePropertyInfoList) { string sourcePropertyInfoName = sourcePropertyInfo.Name; if (resNamePro.ContainsKey(sourcePropertyInfoName)) { //// 獲取數據源對應屬性值 object sourceProValue = sourcePropertyInfo.GetValue(sourceInfo, null); //// 給返回的對象相同屬性賦值 FillProValue(resInfo, sourcePropertyInfo, resNamePro[sourcePropertyInfoName], sourceProValue); } } resList.Add(resInfo); } } } #endregion #region 對象值映射賦值(屬性名稱根據被指映射) /// <summary> /// 對象值映射賦值(屬性名稱根據被指映射) /// </summary> /// <typeparam name="T">需要賦值的對象:不能為空</typeparam> /// <typeparam name="TA">數據源:不能為空</typeparam> /// <param name="sourceList">數據源</param> /// <param name="resInfo">需要賦值的對象</param> public static void MappingToListFunc<T, TA>(this List<TA> sourceList, List<T> resList) where T : class, new() where TA : class, new() { if (sourceList == null || resList == null) { return; } Type sourceType = typeof(TA); Type resType = typeof(T); //// 獲取數據源public屬性集合 PropertyInfo[] sourcePropertyInfoList = sourceType.GetProperties(); if (sourcePropertyInfoList != null) { //// 獲取返回的對象的共有屬性的名稱集合,數據源不存在的不需要做賦值 var resProList = resType.GetProperties(); Dictionary<string, PropertyInfo> resNamePro = new Dictionary<string, PropertyInfo>(); if (resProList != null) { foreach (var item in resProList) { var isIgnore = item.IsDefined(typeof(IgnoreAttribute), false); if (!isIgnore) { string resProName = item.Name; var mappingName = item.GetCustomAttribute<MappingNameAttribute>()?.MappingName; if (string.IsNullOrWhiteSpace(mappingName)) { resNamePro.Add(resProName, item); } else { resNamePro.Add(mappingName, item); } } } } Dictionary<string, Func<TA, object>> dicGet = new Dictionary<string, Func<TA, object>>(); Dictionary<string, Action<T, object>> dicSet = new Dictionary<string, Action<T, object>>(); foreach (var sourceInfo in sourceList) { //// 給對應(相同)的屬性賦值 T resInfo = new T(); //// 給對應(相同)的屬性賦值 foreach (PropertyInfo sourcePropertyInfo in sourcePropertyInfoList) { string sourcePropertyInfoName = sourcePropertyInfo.Name; if (resNamePro.ContainsKey(sourcePropertyInfoName)) { //// 獲取數據源對應屬性值 Func<TA, object> sourceProGet = null; if (dicGet.ContainsKey(sourcePropertyInfoName)) { sourceProGet = dicGet[sourcePropertyInfoName]; } else { sourceProGet = sourcePropertyInfo.BuildGetLambda<TA>(); dicGet[sourcePropertyInfoName] = sourceProGet; } var sourceProValue = sourceProGet(sourceInfo); //////// 給返回的對象相同屬性賦值 Action<T, object> fieldSetter = null; if (dicSet.ContainsKey(sourcePropertyInfoName)) { fieldSetter = dicSet[sourcePropertyInfoName]; } else { fieldSetter = resNamePro[sourcePropertyInfoName].BuildSetLambda<T>(); dicSet[sourcePropertyInfoName] = fieldSetter; } fieldSetter(resInfo, sourceProValue); } } resList.Add(resInfo); } } } #endregion #region 對象值映射賦值(屬性名稱根據被指映射) /// <summary> /// 對象值映射賦值(屬性名稱根據被指映射) /// </summary> /// <typeparam name="T">需要賦值的對象:不能為空</typeparam> /// <typeparam name="TA">數據源:不能為空</typeparam> /// <param name="sourceInfo">數據源</param> /// <param name="resInfo">需要賦值的對象</param> public static T MappingTo<T, TA>(this TA sourceInfo) where T : class, new() where TA : class, new() { if (sourceInfo == null) { return null; } T resInfo = new T(); Type sourceType = typeof(TA); Type resType = typeof(T); //// 獲取數據源public屬性集合 PropertyInfo[] sourcePropertyInfoList = sourceType.GetProperties(); if (sourcePropertyInfoList != null) { //// 獲取返回的對象的共有屬性的名稱集合,數據源不存在的不需要做賦值 var resProList = resType.GetProperties(); Dictionary<string, PropertyInfo> resNameProDic = new Dictionary<string, PropertyInfo>(); if (resProList != null) { foreach (var item in resProList) { var isIgnore = item.IsDefined(typeof(IgnoreAttribute), false); if (!isIgnore) { string resProName = item.Name; var mappingName = item.GetCustomAttribute<MappingNameAttribute>()?.MappingName; if (string.IsNullOrWhiteSpace(mappingName)) { resNameProDic.Add(resProName, item); } else { resNameProDic.Add(mappingName, item); } } } } //// 給對應(相同)的屬性賦值 foreach (PropertyInfo sourcePropertyInfo in sourcePropertyInfoList) { string sourcePropertyInfoName = sourcePropertyInfo.Name; if (resNameProDic.ContainsKey(sourcePropertyInfoName)) { //// 獲取數據源對應屬性值 object sourceProValue = sourcePropertyInfo.GetValue(sourceInfo, null); //// 給返回的對象相同屬性賦值 FillProValue(resInfo, sourcePropertyInfo, resNameProDic[sourcePropertyInfoName], sourceProValue); } } } return resInfo; } #endregion #region 對象值映射賦值(屬性名稱根據被指映射) /// <summary> /// 對象值映射賦值(屬性名稱根據被指映射) /// </summary> /// <typeparam name="T">需要賦值的對象:不能為空</typeparam> /// <typeparam name="TA">數據源:不能為空</typeparam> /// <param name="sourceList">數據源</param> /// <param name="resInfo">需要賦值的對象</param> public static List<T> MappingToList<T, TA>(this List<TA> sourceList) where T : class, new() where TA : class, new() { if (sourceList == null) { return null; } List<T> resList = new List<T>(); Type sourceType = typeof(TA); Type resType = typeof(T); //// 獲取數據源public屬性集合 PropertyInfo[] sourcePropertyInfoList = sourceType.GetProperties(); if (sourcePropertyInfoList != null) { //// 獲取返回的對象的共有屬性的名稱集合,數據源不存在的不需要做賦值 var resProList = resType.GetProperties(); Dictionary<string, PropertyInfo> resNamePro = new Dictionary<string, PropertyInfo>(); if (resProList != null) { foreach (var item in resProList) { var isIgnore = item.IsDefined(typeof(IgnoreAttribute), false); if (!isIgnore) { string resProName = item.Name; var mappingName = item.GetCustomAttribute<MappingNameAttribute>()?.MappingName; if (string.IsNullOrWhiteSpace(mappingName)) { resNamePro.Add(resProName, item); } else { resNamePro.Add(mappingName, item); } } } } foreach (var sourceInfo in sourceList) { //// 給對應(相同)的屬性賦值 T resInfo = new T(); //// 給對應(相同)的屬性賦值 foreach (PropertyInfo sourcePropertyInfo in sourcePropertyInfoList) { string sourcePropertyInfoName = sourcePropertyInfo.Name; if (resNamePro.ContainsKey(sourcePropertyInfoName)) { //// 獲取數據源對應屬性值 object sourceProValue = sourcePropertyInfo.GetValue(sourceInfo, null); //// 給返回的對象相同屬性賦值 FillProValue(resInfo, sourcePropertyInfo, resNamePro[sourcePropertyInfoName], sourceProValue); } } resList.Add(resInfo); } } return resList; } #endregion #region 對象值映射賦值(屬性名稱根據被指映射) /// <summary> /// 對象值映射賦值(屬性名稱根據被指映射) /// </summary> /// <typeparam name="T">需要賦值的對象:不能為空</typeparam> /// <typeparam name="TA">數據源:不能為空</typeparam> /// <param name="sourceList">數據源</param> /// <param name="resInfo">需要賦值的對象</param> public static List<T> MappingToListFunc<T, TA>(this List<TA> sourceList) where T : class, new() where TA : class, new() { if (sourceList == null) { return null; } List<T> resList = new List<T>(); Type sourceType = typeof(TA); Type resType = typeof(T); //// 獲取數據源public屬性集合 PropertyInfo[] sourcePropertyInfoList = sourceType.GetProperties(); if (sourcePropertyInfoList != null) { //// 獲取返回的對象的共有屬性的名稱集合,數據源不存在的不需要做賦值 var resProList = resType.GetProperties(); Dictionary<string, PropertyInfo> resNamePro = new Dictionary<string, PropertyInfo>(); if (resProList != null) { foreach (var item in resProList) { var isIgnore = item.IsDefined(typeof(IgnoreAttribute), false); if (!isIgnore) { string resProName = item.Name; var mappingName = item.GetCustomAttribute<MappingNameAttribute>()?.MappingName; if (string.IsNullOrWhiteSpace(mappingName)) { resNamePro.Add(resProName, item); } else { resNamePro.Add(mappingName, item); } } } } Dictionary<string, Func<TA, object>> dicGet = new Dictionary<string, Func<TA, object>>(); Dictionary<string, Action<T, object>> dicSet = new Dictionary<string, Action<T, object>>(); foreach (var sourceInfo in sourceList) { //// 給對應(相同)的屬性賦值 T resInfo = new T(); //// 給對應(相同)的屬性賦值 foreach (PropertyInfo sourcePropertyInfo in sourcePropertyInfoList) { string sourcePropertyInfoName = sourcePropertyInfo.Name; if (resNamePro.ContainsKey(sourcePropertyInfoName)) { //// 獲取數據源對應屬性值 Func<TA, object> sourceProGet = null; if (dicGet.ContainsKey(sourcePropertyInfoName)) { sourceProGet = dicGet[sourcePropertyInfoName]; } else { sourceProGet = sourcePropertyInfo.BuildGetLambda<TA>(); dicGet[sourcePropertyInfoName] = sourceProGet; } var sourceProValue = sourceProGet(sourceInfo); //////// 給返回的對象相同屬性賦值 Action<T, object> fieldSetter = null; if (dicSet.ContainsKey(sourcePropertyInfoName)) { fieldSetter = dicSet[sourcePropertyInfoName]; } else { fieldSetter = resNamePro[sourcePropertyInfoName].BuildSetLambda<T>(); dicSet[sourcePropertyInfoName] = fieldSetter; } fieldSetter(resInfo, sourceProValue); } } resList.Add(resInfo); } } return resList; } #endregion #region 比較--兩個類型一樣的實體類對象的值 /// 比較--兩個類型一樣的實體類對象的值 /// </summary> /// <typeparam name="T"></typeparam> /// <param name="oneT"></param> /// <param name="twoT"></param> /// <returns>不一樣內容的名稱和值的差異</returns> public static string CompareType<T>(T oneT, T twoT) { string strFALSE = "FALSE"; string result = string.Empty;//兩個類型作比較時使用,如果有不一樣的就false Type typeOne = oneT.GetType(); Type typeTwo = twoT.GetType(); //如果兩個T類型不一樣 就不作比較 if (!typeOne.Equals(typeTwo)) { return strFALSE; } PropertyInfo[] pisOne = typeOne.GetProperties(); //獲取所有公共屬性(Public) PropertyInfo[] pisTwo = typeTwo.GetProperties(); //如果長度為0返回false if (pisOne.Length <= 0 || pisTwo.Length <= 0) { return strFALSE; } //如果長度不一樣,返回false if (!(pisOne.Length.Equals(pisTwo.Length))) { return strFALSE; } //遍歷兩個T類型,遍歷屬性,並作比較 for (int i = 0; i < pisOne.Length; i++) { //獲取屬性名 string oneName = pisOne[i].Name; string twoName = pisTwo[i].Name; //獲取屬性的值 object oneValue = pisOne[i].GetValue(oneT, null); object twoValue = pisTwo[i].GetValue(twoT, null); if (oneName.Equals(twoName)) { //值不同的類型顯示不同內容 bool flag = (oneValue == null && twoValue == null) || ((oneValue != null && twoValue != null) && (oneValue.Equals(twoValue))); if (!flag) { if (string.IsNullOrEmpty(result)) { result = string.Format("{0}: {1} -> {2}", oneName, oneValue, twoValue); } else { result += string.Format("; {0}: {1} -> {2}", oneName, oneValue, twoValue); } } } else { result = strFALSE; break; } } return result; } #endregion #region 私有方法 /// <summary> /// 給屬性賦值,類型不一致轉換為對應類型 /// </summary> /// <typeparam name="T"></typeparam> /// <param name="resObj">返回的對象</param> /// <param name="sourceProperty">數據源屬性</param> /// <param name="resProperty">被賦值的屬性</param> /// <param name="sourcevalue">數據源屬性值</param> private static void FillProValue<T>(T resObj, PropertyInfo sourceProperty, PropertyInfo resProperty, object sourcevalue) { if (sourceProperty.PropertyType != resProperty.PropertyType) { if (!resProperty.PropertyType.IsGenericType) { var newValue = string.IsNullOrEmpty(sourcevalue?.ToString()) ? null : Convert.ChangeType(sourcevalue, resProperty.PropertyType); //非泛型 resProperty.SetValue(resObj, newValue, null); } else { //泛型Nullable<> Type genericTypeDefinition = resProperty.PropertyType.GetGenericTypeDefinition(); if (genericTypeDefinition == typeof(Nullable<>)) { var newValue = string.IsNullOrEmpty(sourcevalue?.ToString()) ? null : Convert.ChangeType(sourcevalue, Nullable.GetUnderlyingType(resProperty.PropertyType)); resProperty.SetValue(resObj, newValue, null); } } } else { resProperty.SetValue(resObj, sourcevalue, null); } } /// <summary> /// 屬性取值,拼裝lambda表達式 /// </summary> /// <typeparam name="T"></typeparam> /// <param name="properInfo">取值的屬性</param> /// <returns></returns> private static Func<T, object> BuildGetLambda<T>(this PropertyInfo properInfo) { //// 獲取屬性的對象類型 var targetType = properInfo.DeclaringType; //// 定義屬性的對象別名 t var exinstance = Expression.Parameter(targetType, "t"); //// t.xxx var lambdaBody = Expression.MakeMemberAccess(exinstance, properInfo); //// 值轉換為object類型 var dataConvertToObject = Expression.Convert(lambdaBody, typeof(object)); //// 定義lambda表達式並預編譯 var resLambda = Expression.Lambda<Func<T, object>>(dataConvertToObject, exinstance); return resLambda.Compile(); } /// <summary> /// 屬性賦值、拼裝lambda表達式 /// </summary> /// <typeparam name="T"></typeparam> /// <param name="properInfo">賦值的屬性</param> /// <returns></returns> private static Action<T, object> BuildSetLambda<T>(this PropertyInfo properInfo) { var targetType = properInfo.DeclaringType; var resParm = Expression.Parameter(targetType, "t"); var resBody = Expression.MakeMemberAccess(resParm, properInfo); var sourceParm = Expression.Parameter(typeof(object), "p"); var sourceParmConvertedValue = Expression.Convert(sourceParm, properInfo.PropertyType); var lambdaBody = Expression.Assign(resBody, sourceParmConvertedValue); var resLambda = Expression.Lambda<Action<T, object>>(lambdaBody, resParm, sourceParm); return resLambda.Compile(); } #endregion }
public class MappingNameAttribute : System.Attribute { /// <summary> /// 構造函數 /// </summary> /// <param name="mappingName">由對應的屬性映射</param> public MappingNameAttribute(string mappingName ) { this.MappingName = mappingName; } /// <summary> /// 數據源屬性名稱 /// </summary> public string MappingName { get; set; } }
public class IgnoreAttribute : System.Attribute { /// <summary> /// 構造函數 /// </summary> /// <param name="isIgnore">是否忽略</param> public IgnoreAttribute(bool isIgnore=true) { IsIgnore = isIgnore; } /// <summary> /// 是否忽略 /// </summary> public bool IsIgnore { get; set; } }
/// <summary> /// 被賦值對象 /// </summary> public class demo2 { [Ignore] public int? a { get; set; }
[MappingName("ba")] public long? b { get; set; } public string c { get; set; } }