Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

加了一个ModelMapHelper类 #341

Open
xcanel opened this issue Mar 31, 2023 · 1 comment
Open

加了一个ModelMapHelper类 #341

xcanel opened this issue Mar 31, 2023 · 1 comment
Labels
很棒的提议 对整体项目或局部小核心知识点很有帮助 欢迎提交PR,给社区一起做贡献~~

Comments

@xcanel
Copy link

xcanel commented Mar 31, 2023

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Reflection;
using System.Text;

namespace SEP.Common
{
    /// <summary>
    /// 对象转换
    /// </summary>
    public class ModelMapHelper
    {
        /// <summary>
        /// 合并数据 把origin的数据合并到obj中
        /// </summary>
        /// <typeparam name="T1">原类型</typeparam>
        /// <typeparam name="T2">目标类型</typeparam>
        /// <param name="origin">原对象</param>
        /// <param name="obj">目标对象</param>
        /// <param name="allowEmployee">是否允许null或空值</param>
        public static void GetModelMerge<T1, T2>(T1 origin, T2 obj, bool allowEmployee = true)
        {
            var OriginPropertyList = GetPropertyValue<T1>(origin);
            if (obj != null)
            {
                Dictionary<string, string> propertyValue = new Dictionary<string, string>();
                Type type = obj.GetType();
                PropertyInfo[] propertyInfos = type.GetProperties();
                foreach (PropertyInfo property in propertyInfos)
                {
                    string value = "";
                    if (OriginPropertyList.TryGetValue(property.Name, out value))
                    {
                        if (!property.PropertyType.IsGenericType)
                        {
                            //非泛型
                            if (!string.IsNullOrEmpty(value) || allowEmployee)
                                property.SetValue(obj, string.IsNullOrEmpty(value) ? null : Convert.ChangeType(value, property.PropertyType), null);
                        }
                        else
                        {
                            //泛型Nullable<>
                            Type genericTypeDefinition = property.PropertyType.GetGenericTypeDefinition();
                            if (genericTypeDefinition == typeof(Nullable<>))
                            {
                                if (!string.IsNullOrEmpty(value) || allowEmployee)
                                    property.SetValue(obj, string.IsNullOrEmpty(value) ? null : Convert.ChangeType(value, Nullable.GetUnderlyingType(property.PropertyType)), null);
                            }
                        }
                    }
                }

            }
        }

        /// <summary>
        /// 获取对象的属性和值
        /// </summary>
        /// <param name="obj">对象</param>
        /// <returns>返回属性与值一一对应的字典</returns>
        public static Dictionary<string, string> GetPropertyValue<T>(T obj)
        {
            if (obj != null)
            {
                Dictionary<string, string> propertyValue = new Dictionary<string, string>();
                Type type = obj.GetType();
                PropertyInfo[] propertyInfos = type.GetProperties();

                foreach (PropertyInfo item in propertyInfos)
                {
                    switch (item.PropertyType.FullName)
                    {
                        case "System.Int32":
                            propertyValue.Add(item.Name, (item.GetValue(obj, null) == null ? "" : item.GetValue(obj, null)).ObjToInt().ToString());
                            break;
                        case "System.Decimal":
                            propertyValue.Add(item.Name, (item.GetValue(obj, null) == null ? "" : item.GetValue(obj, null)).ObjToDecimal().ToString());
                            break;
                        default:
                            propertyValue.Add(item.Name, (item.GetValue(obj, null) == null ? "" : item.GetValue(obj, null)).ToString());
                            break;
                    }
                }

                return propertyValue;
            }
            return null;
        }


        /// <summary>
        /// 获取对象的主键列表
        /// </summary>
        /// <param name="obj">对象</param>
        /// <returns>返回主键列表</returns>
        public static List<string> GetPropertyPrimaryKeys<T>(T obj)
        {
            if (obj != null)
            {
                List<string> list = new List<string>();
                Type type = obj.GetType();
                PropertyInfo[] propertyInfos = type.GetProperties();

                foreach (PropertyInfo item in propertyInfos)
                {
                    if (item.CustomAttributes != null)
                    {
                        foreach (var attr in item.CustomAttributes)
                        {
                            foreach (var info in attr.NamedArguments)
                            {
                                if (info.MemberName == "IsPrimaryKey"
                                    && (bool)info.TypedValue.Value
                                    && !list.Contains(item.Name))
                                    list.Add(item.Name);
                            }
                        }
                    }
                }

                return list;
            }
            return null;
        }

        /// <summary>
        /// 比较2个对象,不同对象则只比较相同字段
        /// </summary>
        /// <typeparam name="T1"></typeparam>
        /// <typeparam name="T2"></typeparam>
        /// <param name="origin"></param>
        /// <param name="obj"></param>
        /// <param name="oType"></param>
        /// <param name="parts"></param>
        /// <returns></returns>
        public static string CompareModel<T1, T2>(T1 origin, T2 obj, AppEnum.OperationType oType, string parts = "", bool hasPrimaryKey = true) where T1 : class, new() where T2 : class, new()
        {
            if (origin == null)
                origin = new T1();
            if (obj == null)
                obj = new T2();

            if (!string.IsNullOrEmpty(parts))
                parts = "," + parts;
            StringBuilder diffColumns = new StringBuilder(); //差异数据
            var OriginPropertyList = GetPropertyValue<T1>(origin);
            var objPropertyList = GetPropertyValue<T2>(obj);

            var primaryKeysList = GetPropertyPrimaryKeys<T1>(origin);
            StringBuilder diffKeyColumns = new StringBuilder();
            foreach (var originItem in OriginPropertyList)
            {
                if (
                    (oType == AppEnum.OperationType.Update ||
                     oType == AppEnum.OperationType.Add) &&
                    (
                     originItem.Key.StartsWith("Update") ||
                     originItem.Key.StartsWith("Create") ||
                     originItem.Key.EndsWith("Code")
                    )) //更新时 不需要记录创建信息
                {
                    continue;
                }

                string value = "";
                if (objPropertyList.TryGetValue(originItem.Key, out value))
                {
                    if (primaryKeysList.Contains(originItem.Key))
                    {
                        if (RegexExpressHelper.IsValidDemical(value) && value.ObjToDecimal() > 0)
                            diffKeyColumns.AppendLine("\"主键[" + originItem.Key + "]\":\"值[" + value + "]\"");
                    }
                    if (originItem.Value != value)
                    {
                        bool isSameNum = false;
                        if (RegexExpressHelper.IsValidDemical(originItem.Value) && RegexExpressHelper.IsValidDemical(value))
                        {
                            if (originItem.Value.ObjToDecimal() == value.ObjToDecimal())
                                isSameNum = true;
                        }
                        if (!isSameNum)
                        {
                            if (oType == AppEnum.OperationType.Add)
                            {
                                if (diffColumns.Length == 0)
                                    diffColumns.AppendLine("\"" + originItem.Key + "\":\"新增值[" + value + "]\"");
                                else
                                    diffColumns.AppendLine(",\"" + originItem.Key + "\":\"新增值[" + value + "]\"");
                            }
                            else if (oType == AppEnum.OperationType.Update)
                            {
                                if (diffColumns.Length == 0)
                                    diffColumns.AppendLine("\"" + originItem.Key + "\":\"由[" + (string.IsNullOrEmpty(originItem.Value) ? "空值" : originItem.Value) + "]修改为[" + (string.IsNullOrEmpty(value) ? "空值" : value) + "]\"");
                                else
                                    diffColumns.AppendLine(",\"" + originItem.Key + "\":\"由[" + (string.IsNullOrEmpty(originItem.Value) ? "空值" : originItem.Value) + "]修改为[" + (string.IsNullOrEmpty(value) ? "空值" : value) + "]\"");
                            }
                            else
                            {
                                if (diffColumns.Length == 0)
                                    diffColumns.AppendLine("\"" + originItem.Key + "\":\"值[" + (string.IsNullOrEmpty(originItem.Value) ? "空值" : originItem.Value) + "]\"");
                                else
                                    diffColumns.AppendLine(",\"" + originItem.Key + "\":\"值[" + (string.IsNullOrEmpty(originItem.Value) ? "空值" : originItem.Value) + "]\"");
                            }
                        }
                    }
                }
            }
            if (diffColumns.Length > 0)
            {
                if (diffKeyColumns.Length > 0)
                    return "{" + diffKeyColumns.ToString() + "," + diffColumns.ToString() + parts + "}";
                else
                    return "{" + diffColumns.ToString() + parts + "}";
            }
            else
                return "";
        }

        public static string CompareModelMultiple<T1, T2>(List<T1> origin, List<T2> obj, AppEnum.OperationType oType) where T1 : class, new() where T2 : class, new()
        {
            if (origin == null && obj == null)
                return null;

            if (origin == null || origin.Count == 0)
            {
                origin = new List<T1>();
                for (int i = 0; i < obj.Count; i++)
                    origin.Add(new T1());
            }
            if (obj == null || obj.Count == 0)
            {
                obj = new List<T2>();
                for (int i = 0; i < origin.Count; i++)
                    obj.Add(new T2());
            }


            StringBuilder diffColumnsList = new StringBuilder(); //差异数据
            for (int i = 0; i < origin.Count; i++)
            {
                StringBuilder diffColumns = new StringBuilder();
                var OriginPropertyList = GetPropertyValue<T1>(origin[i]);
                var objPropertyList = GetPropertyValue<T2>(obj[i]);
                foreach (var originItem in OriginPropertyList)
                {
                    if (oType == AppEnum.OperationType.Add && (
                        originItem.Key.Equals("CreateTime") ||
                        originItem.Key.Equals("CreateUser") ||
                        originItem.Key.Equals("CreateUserName") ||
                        originItem.Key.EndsWith("Code")
                        ))
                    {
                        continue;
                    }
                    if (oType == AppEnum.OperationType.Update && (
                        originItem.Key.Equals("UpdateTime") ||
                        originItem.Key.Equals("UpdateUser") ||
                        originItem.Key.Equals("UpdateUserName") ||
                        originItem.Key.EndsWith("Code")
                        ))
                    {
                        continue;
                    }

                    string value = "";
                    if (objPropertyList.TryGetValue(originItem.Key, out value))
                    {
                        if (originItem.Value != value)
                        {
                            bool isSameNum = false;
                            if (RegexExpressHelper.IsValidDemical(originItem.Value) && RegexExpressHelper.IsValidDemical(value))
                            {
                                if (originItem.Value.ObjToDecimal() == value.ObjToDecimal())
                                    isSameNum = true;
                            }
                            if (!isSameNum)
                            {
                                if (oType == AppEnum.OperationType.Add)
                                {
                                    if (diffColumns.Length == 0)
                                        diffColumns.AppendLine("\"" + originItem.Key + "\":\"新增值[" + value + "]\"");
                                    else
                                        diffColumns.AppendLine(",\"" + originItem.Key + "\":\"新增值[" + value + "]\"");
                                }
                                else if (oType == AppEnum.OperationType.Update)
                                {
                                    if (diffColumns.Length == 0)
                                        diffColumns.AppendLine("\"" + originItem.Key + "\":\"由[" + (string.IsNullOrEmpty(originItem.Value) ? "空值" : originItem.Value) + "]修改为[" + (string.IsNullOrEmpty(value) ? "空值" : value) + "]\"");
                                    else
                                        diffColumns.AppendLine(",\"" + originItem.Key + "\":\"由[" + (string.IsNullOrEmpty(originItem.Value) ? "空值" : originItem.Value) + "]修改为[" + (string.IsNullOrEmpty(value) ? "空值" : value) + "]\"");
                                }
                                else
                                {
                                    if (diffColumns.Length == 0)
                                        diffColumns.AppendLine("\"" + originItem.Key + "\":\"值[" + (string.IsNullOrEmpty(originItem.Value) ? "空值" : originItem.Value) + "]\"");
                                    else
                                        diffColumns.AppendLine(",\"" + originItem.Key + "\":\"值[" + (string.IsNullOrEmpty(originItem.Value) ? "空值" : originItem.Value) + "]\"");
                                }
                            }
                        }
                    }
                }
                if (diffColumns.Length > 0)
                {
                    //数据前后添加{} 或者 ,{}
                    if (diffColumnsList.Length > 0)
                        diffColumns.Insert(0, ",{");
                    else
                        diffColumns.Insert(0, "{");
                    diffColumns.Append("}");
                }
                diffColumnsList.Append(diffColumns);
            }

            if (diffColumnsList.Length > 0)
                return "[" + diffColumnsList.ToString() + "]";
            else
                return "";
        }


        /// <summary>
        /// 获取枚举值上的Description特性的说明
        /// </summary>
        /// <typeparam name="T">枚举类型</typeparam>
        /// <param name="obj">枚举值</param>
        /// <returns>特性的说明</returns>
        public static string GetEnumDescription<T>(T obj)
        {
            var type = obj.GetType();
            FieldInfo field = type.GetField(Enum.GetName(type, obj));
            DescriptionAttribute descAttr = Attribute.GetCustomAttribute(field, typeof(DescriptionAttribute)) as DescriptionAttribute;
            if (descAttr == null)
            {
                return string.Empty;
            }
            return descAttr.Description;
        }

    }
}

使用方法:
新增或更新数据,我这样处理:
image

记录日志,这样处理:
image

前台解析日志:
image

image

枚举类型根据自己需要定义:

/// <summary>
        /// 操作类型
        /// </summary>
        public enum OperationType
        {
            [Description("新建资料")]
            Add = 0,
            [Description("更新资料")]
            Update = 1,
            [Description("删除资料")]
            Delete = 2,
            [Description("登录")]
            Login = 3
        }

@anjoy8 anjoy8 added 欢迎提交PR,给社区一起做贡献~~ 很棒的提议 对整体项目或局部小核心知识点很有帮助 labels Mar 31, 2023
@NingLiu1998
Copy link

这个很实用哎,等保必备,提PR了吗

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
很棒的提议 对整体项目或局部小核心知识点很有帮助 欢迎提交PR,给社区一起做贡献~~
Projects
None yet
Development

No branches or pull requests

3 participants