首页 > 编程 > C# > 正文

c#动态类型,及动态对象的创建,合并2个对象,map实例

2020-01-24 00:45:16
字体:
来源:转载
供稿:网友

经常会遇到这样的情况,我们在响应客户端请求的数据的时候需要对数据进行处理,比如数据库中的数据是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实例就是小编分享给大家的全部内容了,希望能给大家一个参考,也希望大家多多支持武林网。

发表评论 共有条评论
用户名: 密码:
验证码: 匿名发表