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

作者:jingxian 时间:2023-04-28 17:40:12 

经常会遇到这样的情况,我们在响应客户端请求的数据的时候需要对数据进行处理,比如数据库中的数据是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" }

标签:js,创建,map,对象
0
投稿

猜你喜欢

  • Java实现分布式系统限流

    2022-05-31 22:38:05
  • java二叉查找树的实现代码

    2022-08-12 02:36:43
  • spring mvc url匹配禁用后缀访问操作

    2021-11-19 23:57:34
  • Java基于链表实现栈的方法详解

    2022-07-02 11:39:20
  • Java读写Windows共享文件夹的方法实例

    2022-10-02 02:25:45
  • Android调用外置摄像头的方法

    2021-10-19 01:25:13
  • C#实现求一组数据众数的方法

    2023-06-07 00:11:53
  • 点九图片的显示内容区域应作何理解

    2022-12-27 12:24:30
  • Java中的 FilterInputStream简介_动力节点Java学院整理

    2023-01-21 17:18:56
  • 一文探寻Java装箱和拆箱的奥妙

    2022-08-15 21:41:21
  • Java字符流和字节流对文件操作的区别

    2022-06-08 10:32:01
  • 关于Mybatis-Plus Update更新策略问题

    2022-04-14 19:29:24
  • Java循环对bean的属性进行赋值的实现

    2023-01-27 10:18:05
  • Android控件之SlidingDrawer(滑动式抽屉)详解与实例分享

    2023-07-27 09:26:18
  • Android开发之DrawerLayout实现抽屉效果

    2023-09-30 03:40:59
  • Android Studio实现简易进制转换计算器

    2023-09-17 04:19:29
  • 在eclipse中安装Scala环境的步骤详解

    2022-01-21 09:53:58
  • java并发之原子操作类和非阻塞算法

    2022-04-13 04:39:01
  • C# 开发日志本地化工具

    2023-08-27 21:57:05
  • C#中using指令的几种用法

    2022-01-25 01:35:25
  • asp之家 软件编程 m.aspxhome.com