• 技术文章 >后端开发 >C#.Net教程

    详解c#动态类型和动态对象的创建,合并2个对象,map实例代码

    黄舟黄舟2017-03-21 11:57:31原创1592

    下面小编就为大家带来一篇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实例代码的详细内容,更多请关注php中文网其它相关文章!

    声明:本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn核实处理。
    上一篇:C#动态对象dynamic实现方法和属性动态代码详解 下一篇:自己动手写 PHP MVC 框架(40节精讲/巨细/新人进阶必看)

    相关文章推荐

    • 汇编语言和c语言的区别是什么• go是c语言中关键字吗• 指针数组和数组指针的区别是什么• c语言如何进行强制类型转换• c语言怎么获取数组长度
    1/1

    PHP中文网