三、C#特性学习笔记

该部分对应学习代码的下载地址

1.什么是特性?

特性其实就是一个类,直接或间接继承自Attribute
约定俗成以Attribute结尾,在标记的时候以[]包裹
通过反编译后,在中间语言IL中我们发现标记特性的元素内部都生成了一个.custom,但是我们调用不了
中间语言IL中的特性

//[Obsolete("该类已过时")]
[Obsolete("该类已过时,请使用***代替",true)]
[Serializable]
public class TestClass
{
}

[Obsolete]和[Serializable]这两个特性是.Net内部定义的特性,我们无法修改

2.特性的声明和使用

//AttributeUsage对自定义特性进行约束,设置该特性标记的元素位置,如方法、属性、字段、全部等,建议明确特性所标记的元素
//[AttributeUsage(AttributeTargets.Method,AllowMultiple = true)]
//[AttributeUsage(AttributeTargets.Class,AllowMultiple = true)]
//[AttributeUsage(AttributeTargets.Field,AllowMultiple = true)]
//[AttributeUsage(AttributeTargets.Property,AllowMultiple = true)]
//[AttributeUsage(AttributeTargets.Constructor,AllowMultiple = true)]
[AttributeUsage(AttributeTargets.All,AllowMultiple = true)]
public class RulesAttribute : Attribute
{
    public RulesAttribute()
    {
        Console.WriteLine($"{this.GetType().Name}特性类的无参构造函数");
    }

    public RulesAttribute(int iPar)
    {
        Console.WriteLine($"{this.GetType().Name}特性类的单参构造函数,参数类型:{iPar.GetType()},参数:{iPar}");
    }

    public RulesAttribute(string sPar)
    {
        Console.WriteLine($"{this.GetType().Name}特性类的单参构造函数,参数类型:{sPar.GetType()},参数:{sPar}");
    }

    public RulesAttribute(int iPar,string sPar)
    {
        Console.WriteLine($"{this.GetType().Name}特性类的双参构造函数,参数类型:{iPar.GetType()}{sPar.GetType()},参数:{iPar}{sPar}");
    }

    public string Remark { get; set; }

    public string Description;

    public void Show()
    {
        Console.WriteLine($"通过反射特性调用{this.GetType().Name}的Show方法");
    }
}
[AttributeUsage(AttributeTargets.All,AllowMultiple = true)]
public class RulesChildAttribute : RulesAttribute
{
    public RulesChildAttribute() : base(64,"渡边")
    {
        Console.WriteLine($"{this.GetType().Name}的父类没有空参构造函数时,子类可以:base(参数)来初始化父类的构造函数");
    }
}
public class InvokeCenter
{
    public static void ManagerStudent<T>(T t) where T : Student
    {
        Console.WriteLine($"学生姓名:{t.Name},学生编号:{t.Id}");

        Console.WriteLine($"{t.Answer("渡边")}回答了问题");

        Type type = typeof(T);
        //判断该类型是否被特性RulesAttribute标记,这样可以节省性能,true表示父类被标记也可以算被标记
        if (type.IsDefined(typeof(RulesAttribute), true))
        {
            object[] typeAttributes = type.GetCustomAttributes(typeof(RulesAttribute), true);
            foreach(RulesAttribute attribute in typeAttributes)
            {
                attribute.Show();
            }

            Console.WriteLine();

            foreach(FieldInfo field in type.GetFields())
            {
                if (field.IsDefined(typeof(RulesAttribute)))
                {
                    object[] fieldAttributes = field.GetCustomAttributes(typeof(RulesAttribute), true);
                    foreach(RulesAttribute attribute in fieldAttributes)
                    {
                        attribute.Show();
                    }
                }
            }

            Console.WriteLine();

            foreach(PropertyInfo prop in type.GetProperties())
            {
                if (prop.IsDefined(typeof(RulesAttribute)))
                {
                    object[] propAttributes = prop.GetCustomAttributes(typeof(RulesAttribute), true);
                    foreach(RulesAttribute attribute in propAttributes)
                    {
                        attribute.Show();
                    }
                }
            }

            Console.WriteLine();

            foreach(MethodInfo method in type.GetMethods())
            {
                if (method.IsDefined(typeof(RulesAttribute)))
                {
                    object[] methodAttributes = method.GetCustomAttributes(typeof(RulesAttribute), true);
                    foreach(RulesAttribute attribute in methodAttributes)
                    {
                        attribute.Show();
                    }
                }
            }
        }
    }
}

特性的声明与使用

3.特性应用一

标记的特性,需要用到反射

[AttributeUsage(AttributeTargets.Field,AllowMultiple = true)]
public class RemarkAttribute : Attribute
{
    public string _Remark { get; private set; }

    public RemarkAttribute(string remark)
    {
        this._Remark = remark;
    }
}
public static class RemarkAttributeExtend
{
    public static string GetRemark(this Enum @enum)
    {
        Type type = @enum.GetType();
        FieldInfo field = type.GetField(@enum.ToString());
        if (field.IsDefined(typeof(RemarkAttribute)))
        {
            RemarkAttribute attribute = (RemarkAttribute)field.GetCustomAttribute(typeof(RemarkAttribute));
            return attribute._Remark;
        }

        return @enum.ToString();
    }
}

特性应用一

4.特性应用二

[AttributeUsage(AttributeTargets.Field,AllowMultiple = true)]
public class QQAttribute : Attribute
{
    public int _Min { get; set; }

    public int _Max { get; set; }

    public QQAttribute(int min,int max)
    {
        this._Min = min;
        this._Max = max;
    }

    public bool Validate(object oValue)
    {
        return oValue != null && oValue.ToString().Length >= _Min && oValue.ToString().Length <= _Max;
    }
}
public static class QQAttributeExtend
{
    public static bool Validate(this StudentVIP student)
    {
        Type type = typeof(StudentVIP);
        foreach(FieldInfo field in type.GetFields())
        {
            if (field.IsDefined(typeof(QQAttribute)))
            {
                QQAttribute attribute = (QQAttribute)field.GetCustomAttribute(typeof(QQAttribute));
                return attribute.Validate(student.QQ);
            }
        }
        return false;
    }
}
[AttributeUsage(AttributeTargets.Property,AllowMultiple = true)]
public class SalaryAttribute : Attribute
{
    public long _Salary { get; set; }

    public SalaryAttribute(long salary)
    {
        this._Salary = salary;
    }

    public bool Validate(object oValue)
    {
        return oValue != null && long.TryParse(oValue.ToString(), out long lValue) && lValue >= _Salary;
    }
}
public static class SalaryAttributeExtend
{
    public static bool Validate(this StudentVIP student)
    {
        Type type = typeof(StudentVIP);
        foreach(PropertyInfo prop in type.GetProperties())
        {
            if (prop.IsDefined(typeof(SalaryAttribute)))
            {
                SalaryAttribute attribute = (SalaryAttribute)prop.GetCustomAttribute(typeof(SalaryAttribute));
                return attribute.Validate(student.Salary);
            }
        }

        return false;
    }
}

特性应用二

5.特性+泛型应用

    public abstract class AbstractAttribute : Attribute
    {
        public abstract bool Validate(object oValue);
    }
[AttributeUsage(AttributeTargets.Field,AllowMultiple = true)]
public class QQGenericAttribute : AbstractAttribute
{
    public int _Min { get; set; }

    public int _Max { get; set; }

    public QQGenericAttribute(int min,int max)
    {
        this._Min = min;
        this._Max = max;
    }

    public override bool Validate(object oValue)
    {
        return oValue != null && oValue.ToString().Length >= _Min && oValue.ToString().Length <= _Max;
    }
}
[AttributeUsage(AttributeTargets.Property,AllowMultiple = true)]
public class SalaryGenericAttribute : AbstractAttribute
{
    public long _Salary { get; set; }

    public SalaryGenericAttribute(long salary)
    {
        this._Salary = salary;
    }

    public override bool Validate(object oValue)
    {
        return oValue != null && long.TryParse(oValue.ToString(), out long lValue) && lValue >= _Salary;
    }
}
public class GenericValidateAttributeExtend
{
    public static bool FieldValidate<T>(T t)
    {
        Type type = typeof(T);
        foreach(FieldInfo field in type.GetFields())
        {
            object oValue = field.GetValue(t);
            if (field.IsDefined(typeof(AbstractAttribute)))
            {
                AbstractAttribute attribute = (AbstractAttribute)field.GetCustomAttribute(typeof(AbstractAttribute));
                return attribute.Validate(oValue);
            }
        }

        return false;
    }

    public static bool PropertyValidate<T>(T t)
    {
        Type type = typeof(T);
        foreach(PropertyInfo prop in type.GetProperties())
        {
            object oValue = prop.GetValue(t);
            if (prop.IsDefined(typeof(AbstractAttribute)))
            {
                AbstractAttribute attribute = (AbstractAttribute)prop.GetCustomAttribute(typeof(AbstractAttribute));
                return attribute.Validate(oValue);
            }
        }

        return false;
    }
}

Model

    [Rules(123,"渡边")]
    public class Student
    {
        [Rules(123,"渡边")]
        public Student()
        {
            Console.WriteLine($"{this.GetType().Name}的无参构造函数");
        }
        [Rules(123)]
        public int Id { get; set; }
        [Rules(123,"渡边")]
        public string Name { get; set; }
        
        public Achievement achievement;
        [Rules(123,"渡边",Description = "正在学习",Remark = ".Net班")]
        public void Study()
        {
            Console.WriteLine($"{this.Name}正在学习");
        }
        [Rules(123,"渡边",Description = "回答问题",Remark = ".Net班")]
        public string Answer(string name)
        {
            return $"{name}回答了问题";
        }
    }
    public class StudentVIP : Student
    {
        public string VipGroup { get; set; }
        [QQ(5,10)]
        [QQGeneric(4,8)]
        public long QQ;

        public void HomeWork()
        {
            Console.WriteLine($"调用{this.GetType().Name}的HomeWork方法");
        }
        [Salary(10000)]
        [SalaryGeneric(20000)]
        public long Salary { get; set; }
    }
public enum Achievement
{
    [Remark("优")]
    Excellent = 0,

    [Remark("良")]
    Good = 1,

    [Remark("中")]
    Qulified = 2,

    [Remark("差")]
    Bad = 3
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值