English | 简体中文 | 繁體中文 | Русский язык | Français | Español | Português | Deutsch | 日本語 | 한국어 | Italiano | بالعربية
We often encounter such situations where, when responding to the data requests from clients, we need to process the data. For example, the data in the database may be of int type, which may represent an enumeration or other logical meaning (such designs in databases may be considered from perspectives such as data security and storage capacity), but when displayed to the client, it needs to show its specific meaning.
At this time, our way of handling it is usually}}2If the logic is not complex and is single, you can directly modify the SQL statement to handle the data source, and there is no need to handle anything in the code at this time.
However, if the logic is slightly complex or there are many branches in the judgment, we have to deal with it from the code perspective. It's okay for a single object, but for multiple objects like a list<T>, we have to loop through the fields of an object to do XXX.
As a result, DTO and Arg intermediate objects have emerged. Of course, I personally like this design, but sometimes I am lazy and don't want to write (most of the time I directly write code generators to produce in bulk), such as when testing, taking private work, or demonstrating, just to quickly present the desired effect, I am too lazy to do so. You might say that there are many map libraries on the market, such as automap, tinymap, and even dynamic feature rewriting in json.net, there are many methods, but using a big wheel to do such a small thing is not cost-effective. And as the wheel gets bigger, it has to do more things, I don't want to make it so complex. Well, that's it, I wrote one.
The specific code is pasted below. If you understand it, it will be very convenient to expand or modify it to the effect you want.
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> /// Object interface supporting dynamic output /// </summary> public interface IInjectClass {}} } /// <summary> /// Ignore the properties marked with this tag when outputting dynamically /// </summary> public class IngorePropertyAttribute : Attribute {}} }
Let's test one below:
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 + "(Changed)"; }); 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);
You can reconstruct the characteristic with parameters or modify the injectAct object to suit yourself
Write a test, it's best to change it to expression tree, let's show the code first
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> /// Single object mapping /// </summary> /// <typeparam name="T">Type</typeparam> /// <param name="source">The instance</param> /// <param name="injectAct">The set of map methods</param> /// <returns>The dynamically mapped object</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; //The original property name var _value = p.GetValue(source, null); //The original property value object _resultvalue = _value; //The final mapping 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> /// merge2objects /// </summary> /// <typeparam name="TSource">Object1Type</typeparam> /// <typeparam name="TTarget">Object2Type</typeparam> /// <param name="s">Object1Instance</param> /// <param name="t">Object2Instance</param> /// <returns>Merged dynamic object</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("<>")63; _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> /// merge2objects /// </summary> /// <typeparam name="TSource">Object1Type</typeparam> /// <typeparam name="TTarget">Object2Type</typeparam> /// <param name="s">Object1Instance</param> /// <param name="t">Object2Instance</param> /// <returns>Merged dynamic object</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("<>")63; _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) ?63; null : temp; } return result; } } }
Test it:
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);
Output as follows:
[{"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);
Output as follows:
{"key": "aaa", "value": "111"
The following article on C# dynamic type, and the creation and merging of dynamic objects2This is the entire content of the map instance shared by the editor, hoping to provide a reference for everyone, and also hope that everyone will support the Shouting Tutorial more.