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" }
以上这篇c#动态类型,及动态对象的创建,合并2个对象,map实例就是小编分享给大家的全部内容了,希望能给大家一个参考,也希望大家多多支持。
上一篇: 深入浅析C#泛型类型
下一篇: @Async原理