0

0

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

黄舟

黄舟

发布时间:2017-03-21 11:57:31

|

2626人浏览过

|

来源于php中文网

原创

下面小编就为大家带来一篇c#动态类型,及动态对象的创建,合并2个对象,map实例。小编觉得挺不错的,现在就分享给大家,也给大家做个参考。一起跟随小编过来看看吧

经常会遇到这样的情况,我们在响应客户端请求的数据的时候需要对数据进行处理,比如数据库中的数据是int型,它可能表示某个枚举,或者其它的逻辑意义(数据库这样的设计可能是从数据安全性、存储量上等角度考虑),但是客户端显示的时候需要是它具体的意义。

这个时候我们的处理方式一般都是2中的,如果逻辑不复杂,且单一的话,直接修改sql语句就能处理好数据源,这个时候代码里面不需要处理什么。

但是如果逻辑复稍许复杂或者判断的情况有很多分支,我们不得不从代码角度来处理了。单个对象还好,多个对象比如是个list,那就要循环对某个对象的字段进行XXX了。

进而衍生出了这就出现了DTO,Arg的中间对象,当然,我个人是很喜欢这样的设计的,但是某些时候也会偷懒不想写(多半情况我直接写代码生器批量生产),比如在测试的时候,在接私活的时候,在演示的时候,只为快速呈现想要的效果 都懒得去屑,是的,你会说市面上不是有很多的map库,比如automap,tinymap,甚至json.net里面的动态特性重写,方法当然很多,但用一个大轮子来费力搞这么个小事,我觉得划不来。且轮子越来越大它要干的事越多,我可不想搞的那么复杂,嗯,就是这样,写了个。

具体的代码贴到下面,如果看明白,会很方便的扩展了或修改成自己想要的效果。

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
{
}

下面我们测试一个:

MakeSong
MakeSong

AI音乐生成,生成高质量音乐,仅需30秒的时间

下载
 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);

您可以重新构造带参数的特性或者修改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
      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" }

热门AI工具

更多
DeepSeek
DeepSeek

幻方量化公司旗下的开源大模型平台

豆包大模型
豆包大模型

字节跳动自主研发的一系列大型语言模型

通义千问
通义千问

阿里巴巴推出的全能AI助手

腾讯元宝
腾讯元宝

腾讯混元平台推出的AI助手

文心一言
文心一言

文心一言是百度开发的AI聊天机器人,通过对话可以生成各种形式的内容。

讯飞写作
讯飞写作

基于讯飞星火大模型的AI写作工具,可以快速生成新闻稿件、品宣文案、工作总结、心得体会等各种文文稿

即梦AI
即梦AI

一站式AI创作平台,免费AI图片和视频生成。

ChatGPT
ChatGPT

最最强大的AI聊天机器人程序,ChatGPT不单是聊天机器人,还能进行撰写邮件、视频脚本、文案、翻译、代码等任务。

相关专题

更多
go语言 注释编码
go语言 注释编码

本专题整合了go语言注释、注释规范等等内容,阅读专题下面的文章了解更多详细内容。

32

2026.01.31

go语言 math包
go语言 math包

本专题整合了go语言math包相关内容,阅读专题下面的文章了解更多详细内容。

23

2026.01.31

go语言输入函数
go语言输入函数

本专题整合了go语言输入相关教程内容,阅读专题下面的文章了解更多详细内容。

16

2026.01.31

golang 循环遍历
golang 循环遍历

本专题整合了golang循环遍历相关教程,阅读专题下面的文章了解更多详细内容。

5

2026.01.31

Golang人工智能合集
Golang人工智能合集

本专题整合了Golang人工智能相关内容,阅读专题下面的文章了解更多详细内容。

6

2026.01.31

2026赚钱平台入口大全
2026赚钱平台入口大全

2026年最新赚钱平台入口汇总,涵盖任务众包、内容创作、电商运营、技能变现等多类正规渠道,助你轻松开启副业增收之路。阅读专题下面的文章了解更多详细内容。

268

2026.01.31

高干文在线阅读网站大全
高干文在线阅读网站大全

汇集热门1v1高干文免费阅读资源,涵盖都市言情、京味大院、军旅高干等经典题材,情节紧凑、人物鲜明。阅读专题下面的文章了解更多详细内容。

195

2026.01.31

无需付费的漫画app大全
无需付费的漫画app大全

想找真正免费又无套路的漫画App?本合集精选多款永久免费、资源丰富、无广告干扰的优质漫画应用,涵盖国漫、日漫、韩漫及经典老番,满足各类阅读需求。阅读专题下面的文章了解更多详细内容。

170

2026.01.31

漫画免费在线观看地址大全
漫画免费在线观看地址大全

想找免费又资源丰富的漫画网站?本合集精选2025-2026年热门平台,涵盖国漫、日漫、韩漫等多类型作品,支持高清流畅阅读与离线缓存。阅读专题下面的文章了解更多详细内容。

85

2026.01.31

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
C# 教程
C# 教程

共94课时 | 8.1万人学习

C 教程
C 教程

共75课时 | 4.3万人学习

C++教程
C++教程

共115课时 | 15.1万人学习

关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号 技术交流群
PHP中文网订阅号
每天精选资源文章推送

Copyright 2014-2026 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号