• c# 特性实践


    案例1:比如说有时候我们需要将一些实体转换成另一个实体,并且相互之间没有什么继承关系,不能直接转换。 

    基础类:

    namespace MapperDemo
    {
        /// <summary>
        /// 数据库实体类Student
        /// </summary>
        public class Student
        {
            public long QQ { get; set; }
            public int Age { get; set; }
            public int Id { get; set; }
            public string Name { get; set; }
        }
        /// <summary>
        /// 业务实体类StudentDto 用来绑定UI界面的数据模型。
        ///   
        /// </summary>
        public class StudentDto
        {
            public long QQ { get; set; }
            public int Age { get; set; }
            public int Id { get; set; }
            public string Name { get; set; }
        }
    }

    方法1:可以使用反射来解决,但是需要注意的是这样的话其实也是比较耗性能的。

        class Program
        {
            static void Main(string[] args)
            { 
                Student student = new Student()
                {
                    Id = 1,
                    Age = 23,
                    Name = "张三",
                    QQ = 123123123,
                };
                {
                    //利用反射实现
                    StudentDto dto = Trans<Student, StudentDto>(student);
                } 
                Console.WriteLine("Hello World!");
            }
    
            /// <summary>
            /// 为了代码通用,使用泛型+反射
            /// 反射是比较耗性能的
            /// </summary>
            /// <typeparam name="TIn">传入类型</typeparam>
            /// <typeparam name="TOut">传出类型</typeparam>
            /// <param name="tIn"></param>
            /// <returns></returns>
            private static TOut Trans<TIn, TOut>(TIn tIn)
            {
                Type typeOut = typeof(TOut);
                Type typeIn = typeof(TIn);
                //获取类型的实例对象
                TOut tOut = (TOut)Activator.CreateInstance(typeOut);
                //获取返回数据模型的所有属性信息  要给返回模型赋值,所以要遍历返回模型
                foreach (var prop in typeOut.GetProperties())
                {
                    //获取此属性在传入模型中的信息
                    PropertyInfo property = typeIn.GetProperty(prop.Name);
                    if (property == null)
                    {
                        continue;
                    }
                    prop.SetValue(tOut, property.GetValue(tIn));
    
                }
                //给字段赋值
                foreach (var field in typeOut.GetFields())
                {
                    //获取此属性在传入模型中的信息
                    FieldInfo fieldIn = typeIn.GetField(field.Name);
                    if (fieldIn == null)
                    {
                        continue;
                    }
                    field.SetValue(tOut, fieldIn.GetValue(tIn));
                }
    
                return tOut;
            }
        }

    方法2:用表达式目录树Expression:它是一个数据结构,可以动态拼装,然后Compile()方法可以得到一个委托的实例。

    方法3:使用特性来实现:

    案例2: 比如说我们在提交数据的时候可能要对字段做是否为空验证,字段长度验证等,不使用特性的话我们就要对字段挨个进行判断,但是使用特性可以让我们避免这个操作:

     这是模型类:

        /// <summary>
        /// Company:数据表的真实名称
        /// </summary>
        [TableMappingAttribute("Company")]
        public class CompanyModel
        {
            [LengthAttribute(3, 50)]
            public string CreateTime { get; set; }
            /// <summary>
            /// 在数据库表真实的字段是Name,和这里的不一样
            /// </summary>
            [ColumnMappingAttribute("Name")]
            [LengthAttribute(3, 10)]
            public string NickName { get; set; }
            [RequiredAttribute]
            public Nullable<int> CreatorId { get; set; }
            public Nullable<int> LastModifierId { get; set; }
            public DateTime? LastModifyTime { get; set; }
    
    
        }

    自定义的特性类:

    namespace MyAttribute
    {
        /// <summary>
        /// 必填的自定义特性
        /// 注意:加上    [AttributeUsage(AttributeTargets.Property)],用来限制只能用在属性上
        /// </summary>
        [AttributeUsage(AttributeTargets.Property)]
        public class RequiredAttribute : AbstractAttribute
        {
            /// <summary>
            /// 重写继承方法
            /// </summary>
            /// <param name="value"></param>
            /// <returns></returns>
            public override bool ValidateAll(object value)
            {
                if (value == null || string.IsNullOrWhiteSpace(value.ToString()))
                {
                    return false;
                }
    
                return true;
            }
        }
    
        /// <summary>
        /// 校验长度
        /// </summary>
        [AttributeUsage(AttributeTargets.Property)]
        public class LengthAttribute : AbstractAttribute
        {
            private int _Min = 0;
            private int _Max = 0;
            /// <summary>
            /// 长度范围赋值
            /// </summary>
            /// <param name="min">允许最小长度值</param>
            /// <param name="max">允许最大长度值</param>
            public LengthAttribute(int min, int max)
            {
                this._Min = min;
                this._Max = max;
            }
    
            public int Min()
            {
                return this._Min;
            }
    
            public int Max()
            {
                return this._Max;
            }
            /// <summary>
            /// 重写继承方法
            /// </summary>
            /// <param name="value"></param>
            /// <returns></returns>
            public override bool ValidateAll(object value)
            {
                if (value == null || value.ToString().Length < this._Min || value.ToString().Length > this._Max)
                {
                    return false;
                }
                return true;
            }
        }
    
        /// <summary>
        /// 存在抽象方法就一定要是抽象类
        /// 
        /// </summary>
        [AttributeUsage(AttributeTargets.Property)]
        public abstract class AbstractAttribute : Attribute
        {
            public abstract bool ValidateAll(object value);
        } 
    }

    自定义的特性扩展方法, 

    namespace MyAttribute
    {
        /// <summary>
        /// 自定义的特性扩展方法类
        /// </summary>
        public static class AttributeExtend
        {
            /// <summary>
            /// 通用的数据规则校验--通过泛型
            /// </summary>
            /// <typeparam name="T"></typeparam>
            /// <param name="t"></param>
            /// <returns></returns>
            public static bool Validate<T>(this T t)
            {
                Type type = t.GetType();
                foreach (var item in type.GetProperties())
                {
                    if (item.IsDefined(typeof(AbstractAttribute), true))
                    {
                        object value = item.GetValue(t);
                        foreach (AbstractAttribute attibute in item.GetCustomAttributes(typeof(AbstractAttribute), true))
                        {
                            if (!attibute.ValidateAll(value))
                            {
                                return false;
                            }
                        }
    
                    }
                    else
                    {
                        continue;
                    }
                }
                return true;
            }
    
    
    
    
    
        }
    }

    调用:

      class Program
        {
            static void Main(string[] args)
            {
                SqlHelper sqlHelper = new SqlHelper();
                CompanyModel company = sqlHelper.Query<CompanyModel>(1);
                company.CreatorId = null;
                if (!company.Validate())
                {
                    Console.WriteLine("校验失败");
                } 
     
            } 
        }
  • 相关阅读:
    ajax 跨域 Access-Control-Allow-Origin
    关于 请求参数 传递时 参数字符串里面包含 特殊符号的 解决~
    鼠标滚动事件
    js 选择随机数
    html 关于一行两列 高度不定的实现(不用table)
    关于php跨域操作(主域不同)
    写规范的javascript脚本代码 之for in
    windows服务等获取文件路径文件目录方法
    C#如何在控制台应用程序中加入配置文件
    easyui Microsoft JScript 运行时错误: “JSON”未定义
  • 原文地址:https://www.cnblogs.com/anjingdian/p/15313733.html
Copyright © 2020-2023  润新知