经常会遇到这样的情况,我们在响应客户端请求的数据的时候需要对数据进行处理,比如数据库中的数据是int型,它可能表示某个枚举,或者其它的逻辑意义(数据库这样的设计可能是从数据安全性、存储量上等角度考虑),但是客户端显示的时候需要是它具体的意义。这个时候我们的处理方式一般都是2中的,如果逻辑不复杂,且单一的话,直接修改sql语句就能处理好数据源,这个时候代码里面不需要处理什么。但是如果逻辑复稍许复杂或者判断的情况有很多分支,我们不得不从代码角度来处理了。单个对象还好,多个对象比如是个list
using System.Dynamic;
using System.Reflection;
using System.Collections.Concurrent;
private static readonly ConcurrentDictionary
DynamicObjectProperties = new ConcurrentDictionary();
private IDictionary ToDynamicResult(T classobj, Func injectAct)
where T : IInjectClass, new()
{
var type = typeof(T);
var key = type.TypeHandle;
var dynamicResult = new ExpandoObject() as IDictionary;
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;
}
///
/// 支持动态输出的对象接口
///
public interface IInjectClass
{
}
///
/// 动态输出时忽略此标记的属性
///
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(ist, (k, v) =>
{
if (k != "aa") return v;
return v + "(改变了哦)";
});
var json = Tools.JsonUtils.JsonSerializer(tt);
json = json + "
" + Tools.JsonUtils.JsonSerializer(ToDynamicResult(
new kk
{
aa = "test",
bb = 789,
cc = true,
dd = DateTime.Now.AddDays(2)
}, null));
Response.Write(json);
下面写个测试,改成表达式树最好了,先上个码
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
DynamicObjectProperties = new ConcurrentDictionary();
private static PropertyInfo[] GetObjectProperties()
{
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;
}
///
/// 单个对象映射
///
/// 类型
/// 实例
/// map方法集
/// 映射后的动态对象
public static IDictionary DynamicResult(T source, params MapCondition[] injectAct)//where T : ICustomMap
{
var queryPts = GetObjectProperties();
var dynamicResult = new ExpandoObject() as IDictionary;
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;
}
///
/// 合并2个对象
///
/// 对象1类型
/// 对象2类型
/// 对象1实例
/// 对象2实例
/// 合并后的动态对象
public static IDictionary MergerObject(TSource s, TTarget t)
{
var targetPts = GetObjectProperties();
PropertyInfo[] mergerPts = null;
var _type = t.GetType();
mergerPts = _type.Name.Contains("<>") ? _type.GetProperties() : GetObjectProperties();
var dynamicResult = new ExpandoObject() as IDictionary;
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;
}
///
/// 合并2个对象
///
/// 对象1类型
/// 对象2类型
/// 对象1实例
/// 对象2实例
/// 合并后的动态对象
public static List> MergerListObject(List s, TTarget t)
{
var targetPts = GetObjectProperties();
PropertyInfo[] mergerPts = null;
var _type = t.GetType();
mergerPts = _type.Name.Contains("<>") ? _type.GetProperties() : GetObjectProperties();
var result = new List>();
s.ForEach(x =>
{
var dynamicResult = new ExpandoObject() as IDictionary;
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 kk = new List
{
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(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(
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" }