下面小編就為大家帶來一篇c#動態類型,及動態對象的建立,合并2個對象,map執行個體。小編覺得挺不錯的,現在就分享給大家,也給大家做個參考。一起跟隨小編過來看看吧
經常會遇到這樣的情況,我們在響應用戶端請求的資料的時候需要對資料進行處理,比如資料庫中的資料是int型,它可能表示某個枚舉,或者其它的邏輯意義(資料庫這樣的設計可能是從資料安全性、儲存量上等角度考慮),但是用戶端顯示的時候需要是它具體的意義。
這個時候我們的處理方式一般都是2中的,如果邏輯不複雜,且單一的話,直接修改sql語句就能處理好資料來源,這個時候代碼裡面不需要處理什麼。
但是如果邏輯複稍許複雜或者判斷的情況有很多分支,我們不得不從代碼角度來處理了。單個對象還好,多個對象比如是個list<T>,那就要迴圈對某個對象的欄位進行XXX了。
進而衍生出了這就出現了DTO,Arg的中間對象,當然,我個人是很喜歡這樣的設計的,但是某些時候也會偷懶不想寫(多半情況我直接寫代碼生器批量生產),比如在測試的時候,在接私活的時候,在示範的時候,只為快速呈現想要的效果 都懶得去屑,是的,你會說市面上不是有很多的map庫,比如automap,tinymap,甚至json.net裡面的動態特性重寫,方法當然很多,但用一個大輪子來費力搞這麼個小事,我覺得划不來。且輪子越來越大它要乾的事越多,我可不想搞的那麼複雜,嗯,就是這樣,寫了個。
具體的代碼貼到下面,如果看明白,會很方便的擴充了或修改成自己想要的效果。
using System.Dynamic;using System.Reflection;using System.Collections.Concurrent;private static readonly ConcurrentDictionary<RuntimeTypeHandle, PropertyInfo[]> DynamicObjectProperties = new ConcurrentDictionary<RuntimeTypeHandle, PropertyInfo[]>();private IDictionary<string, Object> ToDynamicResult<T>(T classobj, Func<string, object, object> injectAct) where T : IInjectClass, new(){ var type = typeof(T); var key = type.TypeHandle; var dynamicResult = new ExpandoObject() as IDictionary<string, Object>; PropertyInfo[] queryPts = null; DynamicObjectProperties.TryGetValue(key, out queryPts); if (queryPts == null) { queryPts = type.GetProperties(); DynamicObjectProperties.TryAdd(key, queryPts); } foreach (var p in queryPts) { var attributes = p.GetCustomAttributes(typeof(IngorePropertyAttribute), true); var columnMapping = attributes.FirstOrDefault(); if (columnMapping != null) continue; var _name = p.Name; var _value = p.GetValue(classobj, null); object _tempvalue = _value; if (injectAct != null) _tempvalue = injectAct.Invoke(_name, _value); //var value = Convert.ChangeType(value,typeof(string)); dynamicResult.Add(p.Name, _tempvalue); } return dynamicResult;}/// <summary>/// 支援動態輸出的對象介面/// </summary>public interface IInjectClass{}/// <summary>/// 動態輸出時忽略此標記的屬性/// </summary>public class IngorePropertyAttribute : Attribute{}
下面我們測試一個:
public class kk : IInjectClass { public string aa { get; set; } public int bb { get; set; } [IngoreProperty] public bool cc { get; set; } public DateTime dd { get; set; } }kk ist = new kk();ist.aa = "aaa";ist.bb = 123;ist.cc = false;ist.dd = DateTime.Now;var tt = ToDynamicResult<kk>(ist, (k, v) =>{ if (k != "aa") return v; return v + "(改變了哦)";});var json = Tools.JsonUtils.JsonSerializer(tt);json = json + "<br /><br />" + Tools.JsonUtils.JsonSerializer(ToDynamicResult<kk>( new kk { aa = "test", bb = 789, cc = true, dd = DateTime.Now.AddDays(2) }, null));Response.Write(json);
您可以重新構造帶參數的特性或者修改injectAct對象,改成適合自己的
下面寫個測試,改成運算式樹狀架構最好了,先上個碼
using System;using System.Linq;using System.Dynamic;using System.Reflection;using System.Linq.Expressions;using System.Collections.Generic;using System.Collections.Concurrent;namespace Tools{ public class Class2Map { private static readonly ConcurrentDictionary<RuntimeTypeHandle, PropertyInfo[]> DynamicObjectProperties = new ConcurrentDictionary<RuntimeTypeHandle, PropertyInfo[]>(); private static PropertyInfo[] GetObjectProperties<T>() { var type = typeof(T); var key = type.TypeHandle; PropertyInfo[] queryPts = null; DynamicObjectProperties.TryGetValue(key, out queryPts); if (queryPts == null) { queryPts = type.GetProperties(); DynamicObjectProperties.TryAdd(key, queryPts); } return queryPts; } /// <summary> /// 單個對象映射 /// </summary> /// <typeparam name="T">類型</typeparam> /// <param name="source">執行個體</param> /// <param name="injectAct">map方法集</param> /// <returns>映射後的動態對象</returns> public static IDictionary<string, Object> DynamicResult<T>(T source, params MapCondition[] injectAct)//where T : ICustomMap { var queryPts = GetObjectProperties<T>(); var dynamicResult = new ExpandoObject() as IDictionary<string, Object>; foreach (var p in queryPts) { var attributes = p.GetCustomAttributes(typeof(IngoreProperty), true); if (attributes.FirstOrDefault() != null) continue; var _name = p.Name; //原來是屬性名稱 var _value = p.GetValue(source, null); //原來的屬性值 object _resultvalue = _value; //最終的映射值 if (injectAct != null) { string _tempname = null; var condition = injectAct.FirstOrDefault(x => x.Orginal == _name); if (CheckChangeInfo(condition, out _tempname)) { _resultvalue = condition.fn.Invoke(_value); dynamicResult.Add(_tempname ?? _name, _resultvalue); continue; } } //var value = Convert.ChangeType(value,typeof(string)); dynamicResult.Add(_name, _resultvalue); } return dynamicResult; } /// <summary> /// 合并2個對象 /// </summary> /// <typeparam name="TSource">對象1類型</typeparam> /// <typeparam name="TTarget">對象2類型</typeparam> /// <param name="s">對象1執行個體</param> /// <param name="t">對象2執行個體</param> /// <returns>合并後的動態對象</returns> public static IDictionary<string, Object> MergerObject<TSource, TTarget>(TSource s, TTarget t) { var targetPts = GetObjectProperties<TSource>(); PropertyInfo[] mergerPts = null; var _type = t.GetType(); mergerPts = _type.Name.Contains("<>") ? _type.GetProperties() : GetObjectProperties<TTarget>(); var dynamicResult = new ExpandoObject() as IDictionary<string, Object>; foreach (var p in targetPts) { var attributes = p.GetCustomAttributes(typeof(IngoreProperty), true); if (attributes.FirstOrDefault() != null) continue; dynamicResult.Add(p.Name, p.GetValue(s, null)); } foreach (var p in mergerPts) { var attributes = p.GetCustomAttributes(typeof(IngoreProperty), true); if (attributes.FirstOrDefault() != null) continue; dynamicResult.Add(p.Name, p.GetValue(t, null)); } return dynamicResult; } /// <summary> /// 合并2個對象 /// </summary> /// <typeparam name="TSource">對象1類型</typeparam> /// <typeparam name="TTarget">對象2類型</typeparam> /// <param name="s">對象1執行個體</param> /// <param name="t">對象2執行個體</param> /// <returns>合并後的動態對象</returns> public static List<IDictionary<string, Object>> MergerListObject<TSource, TTarget>(List<TSource> s, TTarget t) { var targetPts = GetObjectProperties<TSource>(); PropertyInfo[] mergerPts = null; var _type = t.GetType(); mergerPts = _type.Name.Contains("<>") ? _type.GetProperties() : GetObjectProperties<TTarget>(); var result = new List<IDictionary<string, Object>>(); s.ForEach(x => { var dynamicResult = new ExpandoObject() as IDictionary<string, Object>; foreach (var p in targetPts) { var attributes = p.GetCustomAttributes(typeof(IngoreProperty), true); if (attributes.FirstOrDefault() != null) continue; dynamicResult.Add(p.Name, p.GetValue(x, null)); } foreach (var p in mergerPts) { var attributes = p.GetCustomAttributes(typeof(IngoreProperty), true); if (attributes.FirstOrDefault() != null) continue; dynamicResult.Add(p.Name, p.GetValue(t, null)); } result.Add(dynamicResult); }); return result; } private static bool CheckChangeInfo(MapCondition condition, out string name) { name = null; bool result = condition != null && condition.fn != null && !string.IsNullOrWhiteSpace(condition.Orginal);//&& //!string.IsNullOrWhiteSpace(condition.NewName); if (result) { var temp = condition.NewName; name = (string.IsNullOrWhiteSpace(temp) || temp.Trim().Length == 0) ? null : temp; } return result; } }}
測試一下:
List<KeyValue> kk = new List<KeyValue> { new KeyValue{key="aaa", value="111"}, new KeyValue{key="bbb", value="222"}, new KeyValue{key="ccc", value="333"}, new KeyValue{key="ddd", value="444"},};var result = Class2Map.MergerListObject<KeyValue, dynamic>(kk, new { p = "jon test" });var json = JsonUtils.JsonSerializer(result);Response.Write(json);
輸出如下:
[{"key":"aaa","value":"111","p":"jon test"},{"key":"bbb","value":"222","p":"jon test"},{"key":"ccc","value":"333","p":"jon test"},{"key":"ddd","value":"444","p":"jon test"}]var result = Class2Map.MergerObject<KeyValue, dynamic>( new KeyValue { key = "aaa", value = "111" }, new { p = "jon test" } );var json = JsonUtils.JsonSerializer(result);Response.Write(json);
輸出如下:
{ "key": "aaa", "value": "111", "p": "jon test" }