C#反射的简单应用

Posted 李公子lm

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了C#反射的简单应用相关的知识,希望对你有一定的参考价值。

使用场景

假如我们需要做这样一个功能,用户可以修改一个列表里的信息,但是系统里需要记录用户修改了哪一条记录的哪几个字段,把改变的的字段之前的旧的数据保留下来,方便用户可以追溯数据,就好像QQ可以查看历史头像一样,User表需要更新,但是同时需要在UserHistory表里把旧的记录保存起来,我们可以怎么做呢?

这里我们把问题简单梳理下,每一条记录可以抽象为一个实体UserDto,用户修改之后提交的也抽象为UserDto,那就变成了比较同一个实体的不同属性的值了。

那就简单了,上代码。

  public static void CompareTwoEntity<T>(T oldModel, T newModel)
        {
            //用来存放比较后的结果
            var entity = new CompareJson();
            Type typeDescription = typeof(DescriptionAttribute);
            if (oldModel != null && newModel != null)
            {
                //反射获取类(泛型)的所有属性信息
                System.Reflection.PropertyInfo[] mPi = typeof(T).GetProperties(System.Reflection.BindingFlags.Instance | System.Reflection.BindingFlags.Public);
                var oldData = new List<OldData>();
                var newData = new List<NewData>();
                //循环获取每一个属性的信息
                for (int i = 0; i < mPi.Length; i++)
                {
                    System.Reflection.PropertyInfo pi = mPi[i];
                    object[] arr = pi.GetCustomAttributes(typeDescription, true);
                    //获取类的属性
                    string atrr = arr.Length > 0 ? ((DescriptionAttribute)arr[0]).Description : pi.Name;

                    //获取属性值
                    object oldObj = pi.GetValue(oldModel, null);
                    object newObj = pi.GetValue(newModel, null);
                    string oldValue = oldObj == null ? "" : oldObj.ToString();
                    string newValue = newObj == null ? "" : newObj.ToString();
                    //判断值是否相同,不相同则把旧值和新值都保存起来。
                    if (oldValue != newValue)
                    {
                        oldData.Add(new OldData {  field = atrr,value=oldValue});
                        newData.Add(new NewData {  field = atrr,value=newValue});
                    }
                }
                entity.oldData = oldData;
                entity.newData = newData;
                var json = Newtonsoft.Json.JsonConvert.SerializeObject(entity);
                Console.WriteLine(json);
            }
        }

这里比较的必须是一个相同的实体不同的实例,通过反射获取类的所有的属性信息,然后循环获取每一个属性的值进行比较,不相同的则把属性和值都保存起来。

这里我们测试一下,实例化一个类两次。

  var oldUser = new User
            {
                Id = "1",
                Age = "21",
                Gender = "女",
                Name = "李四"
            };
            var newUser = new User
            {
                Id = "1",
                Age = "21",
                Gender = "女",
                Name = "丽丽"
            };

从上面的代码可以看出,就一个Name属性不一样,接下来看运行结果。
在这里插入图片描述
已经成功的找出来了。
以下是完整代码。

using System.Runtime.Caching;
using System;
using System.Collections.Generic;
using Microsoft.Extensions.Caching.Memory;
using System.Linq;
using System.ComponentModel;
using System.Net;
using System.Diagnostics;

namespace TestProject
{
    class Program
    {
        static void Main(string[] args)
        {
            var oldUser = new User
            {
                Id = "1",
                Age = "21",
                Gender = "女",
                Name = "李四"
            };
            var newUser = new User
            {
                Id = "1",
                Age = "21",
                Gender = "女",
                Name = "丽丽"
            };
            CompareTwoEntity(oldUser, newUser);
            Console.ReadKey();
        }

        public static void CompareTwoEntity<T>(T oldModel, T newModel)
        {
            //用来存放比较后的结果
            var entity = new CompareJson();
            Type typeDescription = typeof(DescriptionAttribute);
            if (oldModel != null && newModel != null)
            {
                //反射获取类(泛型)的所有属性信息
                System.Reflection.PropertyInfo[] mPi = typeof(T).GetProperties(System.Reflection.BindingFlags.Instance | System.Reflection.BindingFlags.Public);
                var oldData = new List<OldData>();
                var newData = new List<NewData>();
                //循环获取每一个属性的信息
                for (int i = 0; i < mPi.Length; i++)
                {
                    System.Reflection.PropertyInfo pi = mPi[i];
                    object[] arr = pi.GetCustomAttributes(typeDescription, true);
                    //获取类的属性
                    string atrr = arr.Length > 0 ? ((DescriptionAttribute)arr[0]).Description : pi.Name;

                    //获取属性值
                    object oldObj = pi.GetValue(oldModel, null);
                    object newObj = pi.GetValue(newModel, null);
                    string oldValue = oldObj == null ? "" : oldObj.ToString();
                    string newValue = newObj == null ? "" : newObj.ToString();
                    //判断值是否相同,不相同则把旧值和新值都保存起来。
                    if (oldValue != newValue)
                    {
                        oldData.Add(new OldData {  field = atrr,value=oldValue});
                        newData.Add(new NewData {  field = atrr,value=newValue});
                    }
                }
                entity.oldData = oldData;
                entity.newData = newData;
                var json = Newtonsoft.Json.JsonConvert.SerializeObject(entity);
                Console.WriteLine(json);
            }
        }

    }
    class User
    {
        public string Id { get; set; }
        public string Name { get; set; }
        public string Gender { get; set; }
        public string Age { get; set; }
    }
    class CompareJson
    {
        public List<OldData> oldData { get; set; }
        public List<NewData> newData { get; set; }
    }
    class OldData
    {
        public string field { get; set; }
        public string value { get; set; }
    }
    class NewData
    {
        public string field { get; set; }
        public string value { get; set; }
    }


}

study hard and make progress every day.

以上是关于C#反射的简单应用的主要内容,如果未能解决你的问题,请参考以下文章

tolua反射应用

C#基础系列:实现自己的ORM(反射以及Attribute在ORM中的应用)

C#反射之基础应用实例总结

java 反射代码片段

C# 使用反射原理构建接口后台简单架构

C# 使用反射原理构建接口后台简单架构