我们是五月的花海 , 用青春拥抱时代 |

兴想事成

园龄:12年9个月粉丝:25关注:97

C#中关于 object,dynamic 一点使用心得

首先说一下使用场景  WebAPI接口入参使用 object和 dynamic 后续解析和处理

 1.object和dynamic 区别

在.NET中,objectdynamic也有一些区别:

  1. objectobject是.NET中的顶级类,所有类都是object的子类。在C#中,您可以使用object关键字来声明变量,该变量可以存储任何类型的对象引用。

  2. dynamicdynamic是.NET中的一种类型,它允许您在运行时执行动态绑定。这意味着您可以在编译时避免类型检查,而是在运行时确定变量的类型。这使得代码更加灵活,但也可能导致运行时错误。

在C#中,您可以像这样使用它们:

这里使用 Raccoon 代码助手 给出实例代码: (国产免费ai有时候真智障,仅供参考)

object myObject = "Hello, World!";
dynamic myDynamic = "Hello, Dynamic!";

// 以下代码将引发编译错误,因为myObject的类型在编译时被确定
// myObject = 42;

// 以下代码不会引发编译错误,因为myDynamic的类型在运行时被确定
myDynamic = 42;

 

2. 构建json 和 dynamic 对应关系

由于WebAPI接口接收的参数,来自于前端提交,没有一定的类型检查机制(js弱类型), 再加上有些内容不定(参数里面有单个对象,也有数组之类的) 

后端处理 就会显得有点棘手. 

在考虑如何解析这些前端传过来的结构不定对象之前,先复习一下基础知识,(掌握必备知识,才能更好的解决问题)

下面代码默认使用 TestDriven 插件执行, 命名空间有

using System.Collections.Generic;
using System.Text;
using System.Text.RegularExpressions;
using Newtonsoft.Json;
using System.Linq;
using System.Linq.Expressions;
using Newtonsoft.Json.Linq;

2.1 示例代码1: 数组和对象集合

        public static void Test1()
        {
            var defaultStringValue = new List<string> { "" };
            JArray jArrayString = JArray.FromObject(defaultStringValue);
            Console.WriteLine(JsonConvert.SerializeObject(defaultStringValue)); // 输出 [""]
            Console.WriteLine(JsonConvert.SerializeObject(jArrayString));       // 输出 [""]

            var defaultObjValue = new List<object> { new object() };
            JArray jArrayObj = JArray.FromObject(defaultObjValue);
            Console.WriteLine(JsonConvert.SerializeObject(defaultObjValue));    // 输出 [{}]
            Console.WriteLine(JsonConvert.SerializeObject(jArrayObj));          // 输出 [{}]
        }

接下来看一个复杂的对象构造示例:

现有如下json格式字符串 ,构造 dynamic 类型

{"Guid":"3eab6205-6a05-4d09-9dd3-7a004369bb32","names":["张三","李四","王五"],"Params":[{"id_list":["0001"]}]}

说明一下, 上面这个对象象 ,有三个属性,  Guid 是一个 guid字符串, names 是一个数组,  Params 是一个复杂对象(集合)

2.2 示例代码2: 构造复杂对象

        public static void Test02()
        {
            string[] strings = new string[] { "张三", "李四", "王五" };
            JArray jArray = JArray.FromObject(strings);

            JObject jObj_idlist = new JObject();
            JArray j_id_list = JArray.FromObject(new string[] { "0001" });
            JProperty p_id_list = new JProperty("id_list", j_id_list);
            jObj_idlist.Add(p_id_list);
            
            dynamic obj = new
            {
                Guid = Guid.NewGuid().ToString(),
                names = jArray,
                Params = JArray.FromObject(new List<object>() { jObj_idlist })
            };
            Console.WriteLine(JsonConvert.SerializeObject(obj));
        }

2.3 示例代码3:  

 判断一个dynamic 的值类型是 数组(集合),还是单个的对象 ,这里继续使用上面的 dynamic obj 对象

            Console.WriteLine(obj.Guid is JArray);   // False
            Console.WriteLine(obj.names is JArray);  // True
            Console.WriteLine(obj.Params is JArray); // True

 

2.3 示例代码4:  

    public class StudentInfo
    {
        public int Id { get; set; }
        public string Name { get; set; }
        public DateTime Birthday { get; set; }
        public int? Age
        {
            get
            {
                if (Birthday.HasValue)
                {
                    int year = (DateTime.Now - this.Birthday.Value).Days;
                    return year / 365;
                }
                else
                {
                    return null;
                }
            }
        }
    }
    public class TestClass
    {
        public static void Test1()
        {
            StudentInfo stu1 = new StudentInfo() { Id = 1, Name = "张三", Birthday = new DateTime(2000,1,1)};
            Console.WriteLine(JsonConvert.SerializeObject(stu1));
            // 输出  {"Id":1,"Name":"张三","Birthday":"2000-01-01T00:00:00","Age":24}
        }
    }

加入这个参数   {"Id":1,"Name":"张三","Birthday":"2000-01-01T00:00:00","Age":24} 从前端传入, 那么通过 StudentInfo 可以直接接收,

但是如果 不知道这个人的出生年月日,传入的 字符串为 下面这几种情况 

         {"Id":1,"Name":"张三","Birthday":""}          // 反序列化失败

或者  {"Id":1,"Name":"张三","Birthday":"null"} ,   // 反序列化失败

或者  {"Id":1,"Name":"张三","Birthday":null}       // 可成功序列化

        public static void Test2()
        {
            string json1 = "{\"Id\":1,\"Name\":\"张三\",\"Birthday\":\"\"} ";
            StudentInfo stu1 = JsonConvert.DeserializeObject<StudentInfo>(json1);  // 报错
            Console.WriteLine(JsonConvert.SerializeObject(stu1)); 
        }
        public static void Test3()
        {
            string json1 = "{\"Id\":1,\"Name\":\"张三\",\"Birthday\":\"null\"} ";
            StudentInfo stu1 = JsonConvert.DeserializeObject<StudentInfo>(json1);  // 报错
            Console.WriteLine(JsonConvert.SerializeObject(stu1));
        }

        public static void Test4()
        {
            string json1 = "{\"Id\":1,\"Name\":\"张三\",\"Birthday\":null} ";
            StudentInfo stu1 = JsonConvert.DeserializeObject<StudentInfo>(json1); // 可正常解析
            Console.WriteLine(JsonConvert.SerializeObject(stu1));
            // 输出  {"Id":1,"Name":"张三","Birthday":null,"Age":null}
        }

2.3 泛型类 MapHelper<T>预处理:  

为了接口不报错, 这个先用 dynamic obj 接收这个入参, 然后近一步处理

MapHelper
 using System;
using System.Reflection;
using Newtonsoft.Json.Linq;

namespace Common.Helper
{
    /// <summary>
    /// dynamic 数据映射
    /// </summary>
    /// <typeparam name="T">目标实体类</typeparam>
    public class MapHelper<T> where T : new()
    {
        /// <summary>
        ///  将数据源 转换成对应的 目标对象(处理可空类型, 以及 补全缺失的字段)
        /// </summary>
        /// <param name="obj">dynamic 数据源对象</param>
        /// <returns></returns>
        public static dynamic DynamicFormat(dynamic obj)
        {
            JObject jobj = (Newtonsoft.Json.Linq.JObject)obj;

            T model = new T();//不关心对象T的值, 只关心对象T的字段的类型
            Type ts = model.GetType();
            //反射, 获取 T的所有 属性
            PropertyInfo[] PropertyList = ts.GetProperties();
            foreach (PropertyInfo item in PropertyList)
            {
                string colName = item.Name;
                string typeName = "";
                if (item.PropertyType.IsGenericType && item.PropertyType.GetGenericTypeDefinition() == typeof(Nullable<>))
                {
                    //如果是 Nullable<T>, 直接返回 T, 例如 DateTime?  返回 DateTime
                    Type[] arr = item.PropertyType.GetGenericArguments();
                    var columnType = arr[0];
                    typeName = columnType.ToString();
                    // Console.WriteLine($"{colName}的 目标类型是Nullable<{typeName}>");
                }
                else
                {
                    //普通类型, int,string,datetime 等
                    typeName = item.PropertyType.Name;
                }

                //Console.WriteLine("字段:" + colName);
                //Console.WriteLine("类型:" + typeName);

                #region  尝试类型转换
                var s = jobj.GetValue(colName);// {ID:"10"}
                if (s == null)
                {
                    jobj[colName] = null;
                    continue;
                }

                object va = ((Newtonsoft.Json.Linq.JValue)s).Value;//"10"

                if (va == null)
                {
                    jobj[colName] = null;
                    continue;
                }
                else
                {
                    if (typeName == "System.Int32")
                    {
                        int t;
                        bool parseRes = int.TryParse(va.ToString(), out t);
                        if (parseRes)
                        {
                            jobj[colName] = t;
                        }
                        else
                        {
                            jobj[colName] = null;
                        }
                    }
                    else if (typeName == "System.Decimal")
                    {
                        Decimal t;
                        bool parseRes = decimal.TryParse(va.ToString(), out t);
                        if (parseRes)
                        {
                            jobj[colName] = t;
                        }
                        else
                        {
                            jobj[colName] = null;
                        }
                    }

                    else if (typeName == "System.Double")
                    {
                        double t;
                        bool parseRes = double.TryParse(va.ToString(), out t);
                        if (parseRes)
                        {
                            jobj[colName] = t;
                        }
                        else
                        {
                            jobj[colName] = null;
                        }
                    }
                    else if (typeName == "System.Int64")
                    {
                        long t;
                        bool parseRes = long.TryParse(va.ToString(), out t);
                        if (parseRes)
                        {
                            jobj[colName] = t;
                        }
                        else
                        {
                            jobj[colName] = null;
                        }
                    }
                    else if (typeName == "System.DateTime")
                    {
                        DateTime t;
                        bool parseRes = DateTime.TryParse(va.ToString(), out t);
                        if (parseRes)
                        {
                            jobj[colName] = t;
                        }
                        else
                        {
                            DateTime? init = null;

                            jobj[colName] = init;
                        }
                    }
                    else if (typeName == "System.Int16")
                    {
                        short t;
                        bool parseRes = short.TryParse(va.ToString(), out t);
                        if (parseRes)
                        {
                            jobj[colName] = t;
                        }
                        else
                        {
                            jobj[colName] = null;
                        }
                    }
                }
                #endregion
            }
            return jobj;
        }

        public static dynamic DynamicFormatList(dynamic obj)
        {
            JArray jArray = new JArray();
            foreach (dynamic item in obj)
            {
                JObject jObject = JObject.FromObject(item);
                jArray.Add(DynamicFormat(jObject));
            }
            return jArray;
        }
    }
}

 2.3.1 将上面的 Test2() 改为  TestNew2() 

        public static void TestNew2()
        {
            JObject jobj_stu = new JObject();

            JProperty ip_id = new JProperty("Id", 1);
            JProperty ip_name = new JProperty("Name", "张三");
            JProperty ip_birthday = new JProperty("Birthday", "");

            jobj_stu.Add(ip_id);
            jobj_stu.Add(ip_name);
            jobj_stu.Add(ip_birthday);

            string json_ori = JsonConvert.SerializeObject(jobj_stu);
            Console.WriteLine("初始JSON:"+json_ori);
            // 输出 初始JSON:{"Id":1,"Name":"张三","Birthday":""}

            dynamic objNew = MapHelper<StudentInfo>.DynamicFormat(jobj_stu);
            string json_new = JsonConvert.SerializeObject(objNew);
            Console.WriteLine("处理后JSON:" + json_new);
            // 输出 处理后JSON:{"Id":1,"Name":"张三","Birthday":null,"Age":null}
            
            StudentInfo stu1 = JsonConvert.DeserializeObject<StudentInfo>(json_new);
            Console.WriteLine("对象序列化后JSON:"+JsonConvert.SerializeObject(stu1));
            // 输出 对象序列化后JSON:{"Id":1,"Name":"张三","Birthday":null,"Age":null}
        }

 2.3.2 将上面的 Test3() 改为  TestNew3() 

        public static void TestNew3()
        {
            JObject jobj_stu = new JObject();

            JProperty ip_id = new JProperty("Id", 1);
            JProperty ip_name = new JProperty("Name", "张三");
            JProperty ip_birthday = new JProperty("Birthday", "null");

            jobj_stu.Add(ip_id);
            jobj_stu.Add(ip_name);
            jobj_stu.Add(ip_birthday);

            string json_ori = JsonConvert.SerializeObject(jobj_stu);
            Console.WriteLine("初始JSON:"+json_ori);
            // 输出 初始JSON:{"Id":1,"Name":"张三","Birthday":"null"}

            dynamic objNew = MapHelper<StudentInfo>.DynamicFormat(jobj_stu);
            string json_new = JsonConvert.SerializeObject(objNew);
            Console.WriteLine("处理后JSON:" + json_new);
            // 输出 处理后JSON:{"Id":1,"Name":"张三","Birthday":null,"Age":null}
            
            StudentInfo stu1 = JsonConvert.DeserializeObject<StudentInfo>(json_new);
            Console.WriteLine("对象序列化后JSON:"+JsonConvert.SerializeObject(stu1));
            // 输出 对象序列化后JSON:{"Id":1,"Name":"张三","Birthday":null,"Age":null}
        }

 

3. 使用 Dictionary<string,object> 处理 入参

 除了使用 dynamic 和 JObject  之类的处理方式, 还有 使用 Dictionary<string,object>的处理方式,

 var dict = JsonConvert.DeserializeObject<Dictionary<string, object>>(json_ori);

 

4.构造极为复杂的Json对象

 比如有如下json结构的参数

{"Id":1,"Name":"张三","Birthday":"null","Extends":[[]],"Extends2":[[[]],[[]]]}

添加了 Extends 和  Extends2

一眼看上去 好像不是很好构造,下面给出 C#代码 示例

        public static void TestNew5()
        {
            JObject jobj_stu = new JObject();

            JProperty ip_id = new JProperty("Id", 1);
            JProperty ip_name = new JProperty("Name", "张三");
            JProperty ip_birthday = new JProperty("Birthday", "null");

            var l1 = new List<object>() { new List<object>() { }};
            JProperty jp_extends = new JProperty("Extends", JArray.FromObject(l1) );
          
            dynamic p = new List<JArray>() { JArray.FromObject(l1), JArray.FromObject(l1) };
            JProperty jp_extends2 = new JProperty("Extends2", p);

            jobj_stu.Add(ip_id);
            jobj_stu.Add(ip_name);
            jobj_stu.Add(ip_birthday);
            jobj_stu.Add(jp_extends);
            jobj_stu.Add(jp_extends2);

            string json_ori = JsonConvert.SerializeObject(jobj_stu);
            Console.WriteLine("JSON:" + json_ori);
            // 输出 {"Id":1,"Name":"张三","Birthday":"null","Extends":[[]],"Extends2":[[[]],[[]]]}

            var dict =  JsonConvert.DeserializeObject < Dictionary<string, object>>(json_ori);
            Console.WriteLine("JSON:" + JsonConvert.SerializeObject(dict));
            // 输出 {"Id":1,"Name":"张三","Birthday":"null","Extends":[[]],"Extends2":[[[]],[[]]]}
        }

 

关于 object,dynamic ,以及 配合使用  Newtonsoft.Json 库 就先介绍到这里.

posted @   兴想事成  阅读(830)  评论(1编辑  收藏  举报
相关博文:
阅读排行:
· 微软正式发布.NET 10 Preview 1:开启下一代开发框架新篇章
· C# 集成 DeepSeek 模型实现 AI 私有化(本地部署与 API 调用教程)
· DeepSeek R1 简明指南:架构、训练、本地部署及硬件要求
· 没有源码,如何修改代码逻辑?
· NetPad:一个.NET开源、跨平台的C#编辑器
历史上的今天:
2016-06-28 [sql查询] 重复数据只取一条
点击右上角即可分享
微信分享提示
评论
收藏
关注
推荐
深色
回顶
收起
  1. 1 Good-bye My Loneliness ZARD
  2. 2 Say OK Vanessa Hudgens
  3. 3 All The Love In The World The Corrs
  4. 4 Adesso E Fortuna ~炎と永遠~ 加藤いづみ
Say OK - Vanessa Hudgens
00:00 / 00:00
An audio error has occurred, player will skip forward in 2 seconds.

作词 : BIRGISSON, ARNTHOR/KOTECHA, SAVAN

作曲 : Savan Kotecha/Arnthor Birgisson

Vanessa Hudgens - Say OK

Album: V

You are fine

You are fine

You are fine

You are fine

You are sweet

But I'm still a bit naive with my heart

When you're close I don't breathe

I can't find the words to speak

I feel sparks

But I don't wanna be into you

If you are not looking for true love, oh oh

No I don't wanna start seeing you

If I can't be your only one

So tell me when it's not alright

When it's not ok

Will you try to make me feel better?

Will you say alright? (say alright)

Will you say ok? (Say ok)

Will you stick with me through whatever?

Or run away

(Say that it's gonna be alright)

(That it's gonna be ok)

Say OK

When you call I don't know

If I should pick up the phone every time

I'm not like all my friends

Who keep calling up the boys, I'm so shy

But I don't wanna be into you

If you don't treat me the right way

See I can only start seeing you

If you can make my heart feel safe (feel safe)

When it's not alright

When it's not ok

Will you try to make me feel better?

Will you say alright? (say alright)

Will you say ok? (Say ok)

Will you stick with me through whatever?

Or run away

(Say that it's gonna be alright)

(That it's gonna be ok)

(Don't run away, don't run away)

Let me know if it's gonna be you

Boy, you've got some things to prove

Let me know that you'll keep me safe

I don't want you to run away so

Let me know that you'll call on time

Let me know that you won't be shy

Will you wipe my tears away

Will you hold me closer

When it's not alright

When it's not ok

Will you try to make me feel better

Will you say alright? (say alright)

Will you say ok? (Say ok)

Will you stick with me through whatever?

Or run away

(Say that it's gonna be alright)

(That it's gonna be ok)

Say OK

(Don't run away, don't run away)

(Say that it's gonna be alright)

(That it's gonna be ok)

(Don't run away)

Will you say OK

(Say that it's gonna be alright)

(That it's gonna be ok)

(Don't run away)

You are fine

You are fine