經常會遇到這樣的情況,我們在響應客戶端請求的數據的時候需要對數據進行處理,比如數據庫中的數據是int型,它可能表示某個枚舉,或者其它的邏輯意義(數據庫這樣的設計可能是從數據安全性、存儲量上等角度考慮),但是客戶端顯示的時候需要是它具體的意義。
這個時候我們的處理方式一般都是2中的,如果邏輯不復雜,且單一的話,直接修改sql語句就能處理好數據源,這個時候代碼里面不需要處理什么。
但是如果邏輯復稍許復雜或者判斷的情況有很多分支,我們不得不從代碼角度來處理了。單個對象還好,多個對象比如是個list<T>,那就要循環對某個對象的字段進行XXX了。
進而衍生出了這就出現了DTO,Arg的中間對象,當然,我個人是很喜歡這樣的設計的,但是某些時候也會偷懶不想寫(多半情況我直接寫代碼生器批量生產),比如在測試的時候,在接私活的時候,在演示的時候,只為快速呈現想要的效果 都懶得去屑,是的,你會說市面上不是有很多的map庫,比如automap,tinymap,甚至json.net里面的動態特性重寫,方法當然很多,但用一個大輪子來費力搞這么個小事,我覺得劃不來。且輪子越來越大它要干的事越多,我可不想搞的那么復雜,嗯,就是這樣,寫了個。
具體的代碼貼到下面,如果看明白,會很方便的擴展了或修改成自己想要的效果。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
|
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 { } |
下面我們測試一個:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
|
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對象,改成適合自己的
下面寫個測試,改成表達式樹最好了,先上個碼
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
|
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; } } } |
測試一下:
1
2
3
4
5
6
7
8
9
10
11
12
|
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); |
輸出如下:
1
2
3
4
5
6
7
8
9
|
[{ "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); |
輸出如下:
1
|
{ "key" : "aaa" , "value" : "111" , "p" : "jon test" } |
以上這篇c#動態類型,及動態對象的創建,合并2個對象,map實例就是小編分享給大家的全部內容了,希望能給大家一個參考,也希望大家多多支持服務器之家。