c#动态类型,及动态对象的创建,合并2个对象,map实例
经常会遇到这样的情况,我们在响应客户端请求的数据的时候需要对数据进行处理,比如数据库中的数据是int型,它可能表示某个枚举,或者其它的逻辑意义(数据库这样的设计可能是从数据安全性、存储量上等角度考虑),但是客户端显示的时候需要是它具体的意义。
这个时候我们的处理方式一般都是2中的,如果逻辑不复杂,且单一的话,直接修改sql语句就能处理好数据源,这个时候代码里面不需要处理什么。
但是如果逻辑复稍许复杂或者判断的情况有很多分支,我们不得不从代码角度来处理了。单个对象还好,多个对象比如是个list<T>,那就要循环对某个对象的字段进行XXX了。
进而衍生出了这就出现了DTO,Arg的中间对象,当然,我个人是很喜欢这样的设计的,但是某些时候也会偷懒不想写(多半情况我直接写代码生器批量生产),比如在测试的时候,在接私活的时候,在演示的时候,只为快速呈现想要的效果都懒得去屑,是的,你会说市面上不是有很多的map库,比如automap,tinymap,甚至json.net里面的动态特性重写,方法当然很多,但用一个大轮子来费力搞这么个小事,我觉得划不来。且轮子越来越大它要干的事越多,我可不想搞的那么复杂,嗯,就是这样,写了个。
具体的代码贴到下面,如果看明白,会很方便的扩展了或修改成自己想要的效果。
usingSystem.Dynamic;
usingSystem.Reflection;
usingSystem.Collections.Concurrent;
privatestaticreadonlyConcurrentDictionary<RuntimeTypeHandle,PropertyInfo[]>
DynamicObjectProperties=newConcurrentDictionary<RuntimeTypeHandle,PropertyInfo[]>();
privateIDictionary<string,Object>ToDynamicResult<T>(Tclassobj,Func<string,object,object>injectAct)
whereT:IInjectClass,new()
{
vartype=typeof(T);
varkey=type.TypeHandle;
vardynamicResult=newExpandoObject()asIDictionary<string,Object>;
PropertyInfo[]queryPts=null;
DynamicObjectProperties.TryGetValue(key,outqueryPts);
if(queryPts==null)
{
queryPts=type.GetProperties();
DynamicObjectProperties.TryAdd(key,queryPts);
}
foreach(varpinqueryPts)
{
varattributes=p.GetCustomAttributes(typeof(IngorePropertyAttribute),true);
varcolumnMapping=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);
//varvalue=Convert.ChangeType(value,typeof(string));
dynamicResult.Add(p.Name,_tempvalue);
}
returndynamicResult;
}
///<summary>
///支持动态输出的对象接口
///</summary>
publicinterfaceIInjectClass
{
}
///<summary>
///动态输出时忽略此标记的属性
///</summary>
publicclassIngorePropertyAttribute:Attribute
{
}
下面我们测试一个:
publicclasskk:IInjectClass
{
publicstringaa{get;set;}
publicintbb{get;set;}
[IngoreProperty]
publicboolcc{get;set;}
publicDateTimedd{get;set;}
}kkist=newkk();
ist.aa="aaa";
ist.bb=123;
ist.cc=false;
ist.dd=DateTime.Now;
vartt=ToDynamicResult<kk>(ist,(k,v)=>
{
if(k!="aa")returnv;
returnv+"(改变了哦)";
});
varjson=Tools.JsonUtils.JsonSerializer(tt);
json=json+"<br/><br/>"+Tools.JsonUtils.JsonSerializer(ToDynamicResult<kk>(
newkk
{
aa="test",
bb=789,
cc=true,
dd=DateTime.Now.AddDays(2)
},null));
Response.Write(json);
您可以重新构造带参数的特性或者修改injectAct对象,改成适合自己的
下面写个测试,改成表达式树最好了,先上个码
usingSystem;
usingSystem.Linq;
usingSystem.Dynamic;
usingSystem.Reflection;
usingSystem.Linq.Expressions;
usingSystem.Collections.Generic;
usingSystem.Collections.Concurrent;
namespaceTools
{
publicclassClass2Map
{
privatestaticreadonlyConcurrentDictionary<RuntimeTypeHandle,PropertyInfo[]>
DynamicObjectProperties=newConcurrentDictionary<RuntimeTypeHandle,PropertyInfo[]>();
privatestaticPropertyInfo[]GetObjectProperties<T>()
{
vartype=typeof(T);
varkey=type.TypeHandle;
PropertyInfo[]queryPts=null;
DynamicObjectProperties.TryGetValue(key,outqueryPts);
if(queryPts==null)
{
queryPts=type.GetProperties();
DynamicObjectProperties.TryAdd(key,queryPts);
}
returnqueryPts;
}
///<summary>
///单个对象映射
///</summary>
///<typeparamname="T">类型</typeparam>
///<paramname="source">实例</param>
///<paramname="injectAct">map方法集</param>
///<returns>映射后的动态对象</returns>
publicstaticIDictionary<string,Object>DynamicResult<T>(Tsource,paramsMapCondition[]injectAct)//whereT:ICustomMap
{
varqueryPts=GetObjectProperties<T>();
vardynamicResult=newExpandoObject()asIDictionary<string,Object>;
foreach(varpinqueryPts)
{
varattributes=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;
varcondition=injectAct.FirstOrDefault(x=>x.Orginal==_name);
if(CheckChangeInfo(condition,out_tempname))
{
_resultvalue=condition.fn.Invoke(_value);
dynamicResult.Add(_tempname??_name,_resultvalue);
continue;
}
}
//varvalue=Convert.ChangeType(value,typeof(string));
dynamicResult.Add(_name,_resultvalue);
}
returndynamicResult;
}
///<summary>
///合并2个对象
///</summary>
///<typeparamname="TSource">对象1类型</typeparam>
///<typeparamname="TTarget">对象2类型</typeparam>
///<paramname="s">对象1实例</param>
///<paramname="t">对象2实例</param>
///<returns>合并后的动态对象</returns>
publicstaticIDictionary<string,Object>MergerObject<TSource,TTarget>(TSources,TTargett)
{
vartargetPts=GetObjectProperties<TSource>();
PropertyInfo[]mergerPts=null;
var_type=t.GetType();
mergerPts=_type.Name.Contains("<>")?_type.GetProperties():GetObjectProperties<TTarget>();
vardynamicResult=newExpandoObject()asIDictionary<string,Object>;
foreach(varpintargetPts)
{
varattributes=p.GetCustomAttributes(typeof(IngoreProperty),true);
if(attributes.FirstOrDefault()!=null)continue;
dynamicResult.Add(p.Name,p.GetValue(s,null));
}
foreach(varpinmergerPts)
{
varattributes=p.GetCustomAttributes(typeof(IngoreProperty),true);
if(attributes.FirstOrDefault()!=null)continue;
dynamicResult.Add(p.Name,p.GetValue(t,null));
}
returndynamicResult;
}
///<summary>
///合并2个对象
///</summary>
///<typeparamname="TSource">对象1类型</typeparam>
///<typeparamname="TTarget">对象2类型</typeparam>
///<paramname="s">对象1实例</param>
///<paramname="t">对象2实例</param>
///<returns>合并后的动态对象</returns>
publicstaticList<IDictionary<string,Object>>MergerListObject<TSource,TTarget>(List<TSource>s,TTargett)
{
vartargetPts=GetObjectProperties<TSource>();
PropertyInfo[]mergerPts=null;
var_type=t.GetType();
mergerPts=_type.Name.Contains("<>")?_type.GetProperties():GetObjectProperties<TTarget>();
varresult=newList<IDictionary<string,Object>>();
s.ForEach(x=>
{
vardynamicResult=newExpandoObject()asIDictionary<string,Object>;
foreach(varpintargetPts)
{
varattributes=p.GetCustomAttributes(typeof(IngoreProperty),true);
if(attributes.FirstOrDefault()!=null)continue;
dynamicResult.Add(p.Name,p.GetValue(x,null));
}
foreach(varpinmergerPts)
{
varattributes=p.GetCustomAttributes(typeof(IngoreProperty),true);
if(attributes.FirstOrDefault()!=null)continue;
dynamicResult.Add(p.Name,p.GetValue(t,null));
}
result.Add(dynamicResult);
});
returnresult;
}
privatestaticboolCheckChangeInfo(MapConditioncondition,outstringname)
{
name=null;
boolresult=condition!=null&&
condition.fn!=null&&
!string.IsNullOrWhiteSpace(condition.Orginal);//&&
//!string.IsNullOrWhiteSpace(condition.NewName);
if(result)
{
vartemp=condition.NewName;
name=(string.IsNullOrWhiteSpace(temp)||temp.Trim().Length==0)?null:temp;
}
returnresult;
}
}
}
测试一下:
List<KeyValue>kk=newList<KeyValue>
{
newKeyValue{key="aaa",value="111"},
newKeyValue{key="bbb",value="222"},
newKeyValue{key="ccc",value="333"},
newKeyValue{key="ddd",value="444"},
};
varresult=Class2Map.MergerListObject<KeyValue,dynamic>(kk,new{p="jontest"});
varjson=JsonUtils.JsonSerializer(result);
Response.Write(json);
输出如下:
[{"key":"aaa","value":"111","p":"jontest"},{"key":"bbb","value":"222","p":"jontest"},{"key":"ccc","value":"333","p":"jontest"},{"key":"ddd","value":"444","p":"jontest"}]
varresult=Class2Map.MergerObject<KeyValue,dynamic>(
newKeyValue{key="aaa",value="111"},
new{p="jontest"}
);
varjson=JsonUtils.JsonSerializer(result);
Response.Write(json);
输出如下:
{"key":"aaa","value":"111","p":"jontest"}
以上这篇c#动态类型,及动态对象的创建,合并2个对象,map实例就是小编分享给大家的全部内容了,希望能给大家一个参考,也希望大家多多支持毛票票。