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("校验失败");
            } 
 
        } 
    }

 

posted @ 2021-09-20 10:14  安静点--  阅读(60)  评论(0编辑  收藏  举报