C#特性详解一

文章目录

      • 特性无处不在
      • 特性的本质
      • 自定义特性基本语法和使用
        • 自定义特性操作
      • 特性怎么产生价值

特性无处不在

  1. EF–MVC–WCF–Webservice–UnitTest–IOC–AOP–SuperSocket
  2. [Obsolete]编译时就有提示 影响了编译器
  3. [Serializable]对象就可以序列化 影响了程序运行

特性的本质

  1. 特性就是一个类,直接继承/间接继承自Attribute父类
  2. 约定俗成用Attribute结尾,标记时就可以省略掉

自定义特性基本语法和使用

自定义特性类(自定义特需要继承Attribute抽象类):

 public class CustomAttribute : Attribute {
     
 }

特性的约束使用:

[AttributeUsage(AttributeTargets.All, AllowMultiple = true, Inherited = true)]
 public class CustomAttribute : Attribute {
     
 }

指定修饰的对象—能否重复修饰–修饰的特性子类是否生效

自定义特性操作

完整自定义特性类:

 [AttributeUsage(AttributeTargets.All, AllowMultiple = true, Inherited = true)]
    public class CustomAttribute : Attribute
    {
     
        public CustomAttribute()
        {
     
            Console.WriteLine($"{this.GetType().Name} 无参数构造函数执行");
        }
        public CustomAttribute(int id)
        {
     
            Console.WriteLine($"{this.GetType().Name} int参数构造函数执行");
            this._Id = id;
        }
        public CustomAttribute(string name)
        {
     
            Console.WriteLine($"{this.GetType().Name} string参数构造函数执行");
            this._Name = name;
        }

        private int _Id = 0;
        private string _Name = null;

        public string Remark;
        public string Description {
      get; set; }

        public void Show()
        {
     
            Console.WriteLine($"{this._Id}_{this._Name}_{this.Remark} _ {this.Description}");
        }
    }

特性修饰元素时用中括号包裹,然后标记到元素,其实就是调用构造函数
然后可以指定属性 字段
AttributeUsage特性,影响编译器运行,

特性修饰类:

    [Custom]
    [Custom()]
    [Custom(Remark = "123")]
    [Custom(Remark = "123", Description = "456")]
    [Custom(0)]
    [Custom(0, Remark = "123")]
    [Custom(0, Remark = "123", Description = "456")]
    public class Student
    {
     

看来上面示例,感觉自定义特性,好像毫无有意,那框架提供特性究竟是怎么产生价值的呢?
[Obsolete][AttributeUsage] 影响了编译器,这属于系统内置,我们搞不了

特性怎么产生价值

首先说结论:其实就是通过反射。
那为什么能通过反射产生价值呢,通过反编译之后,发现特性会在袁术内部生成.custom的东西但是这个东西我们C#访问不到------简直可以理解为,特性没有产生任何变化。
以下是反编译student类IL的截取:

.class public auto ansi serializable beforefieldinit Student
    extends [mscorlib]System.Object
{
    .custom instance void MyAttribute.CustomAttribute::.ctor()
    .custom instance void MyAttribute.CustomAttribute::.ctor()
    .custom instance void MyAttribute.CustomAttribute::.ctor() = { Remark=string('123') }
    .custom instance void MyAttribute.CustomAttribute::.ctor() = { Remark=string('123') Description=string('456') }
    .custom instance void MyAttribute.CustomAttribute::.ctor(int32) = { int32(0) }
    .custom instance void MyAttribute.CustomAttribute::.ctor(int32) = { int32(0) Remark=string('123') }
    .custom instance void MyAttribute.CustomAttribute::.ctor(int32) = { int32(0) Remark=string('123') Description=string('456') }
    .method public hidebysig specialname rtspecialname instance void .ctor() cil managed
    {
    }
    
     .property instance int32 Id
    {
        .get instance int32 MyAttribute.Student::get_Id()
        .set instance void MyAttribute.Student::set_Id(int32)
        .custom instance void MyAttribute.CustomAttribute::.ctor()
    }
    
      .method public hidebysig instance string Answer(string name) cil managed
    {
        .custom instance void MyAttribute.CustomAttribute::.ctor(int32) = { int32(0) }
        .custom instance void MyAttribute.CustomAttribute::.ctor(int32) = { int32(0) Remark=string('123') }
        .custom instance void MyAttribute.CustomAttribute::.ctor(int32) = { int32(0) Remark=string('123') Description=string('456') }
        .param [1]
        .custom instance void MyAttribute.CustomAttribute::.ctor()
        .maxstack 2
        .locals init (
            [0] string str)
        L_0000: nop 
        L_0001: ldstr "This is {0}"
        L_0006: ldarg.1 
        L_0007: call string [mscorlib]System.String::Format(string, object)
        L_000c: stloc.0 
        L_000d: br.s L_000f
        L_000f: ldloc.0 
        L_0010: ret 
    }

那么框架究竟是怎么产生功能的呢?就是反射,在程序运行的时候能够通过反射找到特性,可以从类型、属性、方法、都可以获取特性实例,要求先IsDefined检测,再获取(实例化)。


程序运行时可以找到特性—那就可以发挥特性的作用–提供额外的信息–提供额外的行为。
那该怎么做呢
特性本身没有用的,这就需要一个第三方InvokeCenter,在这里去主动检测并且使用特性,才能提供功能了。
InvokeCenter类:

public class InvokeCenter
    {
     
        public static void ManagerStudent<T>(T student) where T : Student
        {
     
            Console.WriteLine($"{student.Id}_{student.Name}");
            student.Study();
            student.Answer("123");

            Type type = student.GetType();
            if (type.IsDefined(typeof(CustomAttribute), true))
            {
     
                //type.GetCustomAttribute()
                object[] oAttributeArray = type.GetCustomAttributes(typeof(CustomAttribute), true);
                foreach (CustomAttribute attribute in oAttributeArray)
                {
     
                    attribute.Show();
                    //attribute.Description
                }

                foreach (var prop in type.GetProperties())
                {
     
                    if (prop.IsDefined(typeof(CustomAttribute), true))
                    {
     
                        object[] oAttributeArrayProp = prop.GetCustomAttributes(typeof(CustomAttribute), true);
                        foreach (CustomAttribute attribute in oAttributeArrayProp)
                        {
     
                            attribute.Show();
                        }
                    }
                }
                foreach (var method in type.GetMethods())
                {
     
                    if (method.IsDefined(typeof(CustomAttribute), true))
                    {
     
                        object[] oAttributeArrayMethod = method.GetCustomAttributes(typeof(CustomAttribute), true);
                        foreach (CustomAttribute attribute in oAttributeArrayMethod)
                        {
     
                            attribute.Show();
                        }
                    }
                }

            }

        }

    }

StudentVip类继承Student:

 [Custom(123, Remark = "VIP", Description = ".Net高级班的学员")]
    [Serializable]
    public class StudentVip : Student
    {
     
        [Custom(123, Remark = "VIP", Description = ".Net高级班的学员")]
        public string VipGroup {
      get; set; }

        [Custom(123, Remark = "VIP", Description = ".Net高级班的学员")]
        public void Homework()
        {
     
            Console.WriteLine("Homework");
        }


    }

测试运行:

 
Student student = new StudentVip()
{
     
    Id = 123,
    Name = "Alxe"
};
InvokeCenter.ManagerStudent<Student>(student);
              

控台打印结果:

123_Alxe
这里是Alxe跟着Eleven老师学习
CustomAttribute int参数构造函数执行
CustomAttribute 无参数构造函数执行
CustomAttribute 无参数构造函数执行
CustomAttribute 无参数构造函数执行
CustomAttribute 无参数构造函数执行
CustomAttribute int参数构造函数执行
CustomAttribute int参数构造函数执行
CustomAttribute int参数构造函数执行
123__VIP _ .Net高级班的学员
0__ _
0__ _
0__123 _
0__123 _ 456
0__ _
0__123 _
0__123 _ 456
CustomAttribute int参数构造函数执行
123__VIP _ .Net高级班的学员
CustomAttribute 无参数构造函数执行
0__ _
CustomAttribute int参数构造函数执行
123__VIP _ .Net高级班的学员
CustomAttribute 无参数构造函数执行
0__ _
CustomAttribute int参数构造函数执行
CustomAttribute int参数构造函数执行
CustomAttribute int参数构造函数执行
0__ _
0__123 _
0__123 _ 456

你可能感兴趣的:(C#基础语法学习笔记,.NET学习笔记,高级课程,c#)