zoukankan      html  css  js  c++  java
  • 再次深入 C# Attribute

    • 了解attribute

    Attribute 只是将一些附加信息与某个目标元素关联起来的方式。

    Attribute 是一个类,这个类可以提供一些字段和属性,不应提供公共方法,事件等。在定义attribute类的构造方法,字段和属性时,对数据类型有严格的要求,一般要求为: Boolean, Char, Byte, Sbyte, Int16, UInt16, Int32, Int64,Single, Double, String, Type, Object, Enum, 可以使用数组,但是并不提倡使用。

    • 使用attribute

     1 [AttributeUsage(AttributeTargets.Property | AttributeTargets.Field, Inherited = false)]
     2     [Conditional("Specify")]
     3     public class DisplayNameAttribute : Attribute
     4     {
     5         public string PropertyName { get; set; }
     6 
     7         public DisplayNameAttribute()
     8         { }
     9 
    10         public DisplayNameAttribute(string propertyName)
    11         {
    12             this.PropertyName = propertyName;
    13         }
    14     }
    • 检测attribute
    1.  attribute定义和应用之后还没有任何意义,只有在运行的时候去检测,然后根据对应的attribute做一些不同事情才让attribute变得有意义,那么如何检测attribute呢?

    方法名称

    说明

    IsDefined

    如果至少有一个指定的Attribute派生类的实例与目标关联,就返回true。这个方法效率很高,因为他不构造(反序列化)attribute类的任何实例

    GetCustomAttributes

    返回一个数组,其中每个元素都是应用于目标的指定attribute类的一个实例。

    如果不为这个方法指定具体的attribute类,数组中包含的就是已应用的所有attribute的实例,不管他们是什么类。每个实例都使用编译时指定的参数、字段和属性来构造(反序列化)。如果目标没有应用任何attribute类的实例,就返回一个空数组。该方法通常用于已将AllowMultiple 设为true的attribute

    GetCustomAttribute

    返回应用于目标的指定attribute类的一个实例。实例使用编译是指定的参数、字段和属性来构造(反序列化)。如果目标没有应用任何attribute类的实例,就返回null。如果目标应用了制定attribute的多个实例,抛出异常AmbiguousMatchException. 因此该方法通常用于AllowMultiple=false的attribute

         最后的例子中展示了如何使用这些方法。

    2.   上面的方法在检测时进行了attribute对象的构造(需要反序列化),这样有可能调用set访问器和构造方法,可能出现安全风险(未知代码在AppDomain中运行)。因此可以使用CustomAttributeData类中定的静态方法进行检测

     1 public override string ToString()
     2         {
     3             //在子类中对父类中的方法进行重写,使用不创建attribute对象不执行代码(反序列化)的方法
     4             StringBuilder value = new StringBuilder();
     5             if (!this.GetType().IsClass)
     6                 return value.ToString();
     7             PropertyInfo[] properties = this.GetType().GetProperties();
     8 
     9             foreach (var property in properties)
    10             {
    11                 string propertyName = property.Name;
    12                 IList<CustomAttributeData> list = CustomAttributeData.GetCustomAttributes(property);
    13                 foreach (var item in list)
    14                 {
    15                     if (item.Constructor.DeclaringType == typeof(DisplayNameAttribute))
    16                     {
    17                         Console.Write("This property applies DisplayNameAttribute.");
    18                     }
    19                 }
    20             }
    21             return base.ToString();
    22         }
    • 条件attribute

    应用attribute时生成元数据,如果想让attribute在编译是不生成元数据可以使用条件编译,下面是例子

     1 #define Specify
     2 //#define UnSpecify
     3 
     4 namespace Attribute
     5 {
     6     using System;
     7     using System.Collections.Generic;
     8     using System.Linq;
     9     using System.Text;
    10     using System.Reflection;
    11     using System.Diagnostics;
    12 
    13     public class Pepople
    14     {
    15         [DisplayName("姓名")]
    16         [TestDemoAttribute]
    17         public string Name { get; set; }
    18      }
    19 
    20     public class Man : Pepople
    21     {
    22         [DisplayName("年龄")]
    23         public int Age { get; set; }
    24 
    25         public float Height { get; set; }
    26     }
    27 
    28     [AttributeUsage(AttributeTargets.Property | AttributeTargets.Field, Inherited = false)]
    29     [Conditional("Specify")]
    30     public class DisplayNameAttribute : Attribute
    31     {
    32         public string PropertyName { get; set; }
    33 
    34         public DisplayNameAttribute()
    35         { }
    36 
    37         public DisplayNameAttribute(string propertyName)
    38         {
    39             this.PropertyName = propertyName;
    40         }
    41     }
    42 
    43     [Conditional("UnSpecify")]
    44     public class TestDemoAttribute : Attribute
    45     { }
    46 }
    47 条件attribute

     注意:赘述一句,在C#中进行预定义时,必须在文件在最前面

     我们用ildasm查看元数据得知,TestDemoAttribute 没有被编译成员数据,而DisplayNameAttribute被编译成了元数据

     

    • 实例

    对上面提到的知识写了个例子,以便加强知识的理解运用。

     1 #define Specify
     2 //#define UnSpecify
     3 
     4 namespace Attribute
     5 {
     6     using System;
     7     using System.Collections.Generic;
     8     using System.Linq;
     9     using System.Text;
    10     using System.Reflection;
    11     using System.Diagnostics;
    12 
    13     public class Pepople
    14     {
    15         [DisplayName("姓名")]
    16         [TestDemoAttribute]
    17         public string Name { get; set; }
    18 
    19         public override string ToString()
    20         {
    21             StringBuilder value = new StringBuilder();
    22             if (!this.GetType().IsClass)
    23                 return value.ToString();
    24             PropertyInfo[] properties = this.GetType().GetProperties();
    25 
    26             foreach (var property in properties)
    27             {
    28                 string propertyName = property.Name;
    29                 if (property.IsDefined(typeof(DisplayNameAttribute), false))
    30                 {
    31                     DisplayNameAttribute attr = (DisplayNameAttribute)Attribute.GetCustomAttribute(property, typeof(DisplayNameAttribute));
    32                     if (attr != null)
    33                     {
    34                         propertyName = attr.PropertyName;
    35                     }
    36                 }
    37                 value.Append(propertyName);
    38                 value.Append("	");
    39                 value.Append(property.GetValue(this, null));
    40                 value.Append("
    
    ");
    41             }
    42 
    43             return value.ToString();
    44         }
    45     }
    46 
    47     public class Man : Pepople
    48     {
    49         [DisplayName("年龄")]
    50         public int Age { get; set; }
    51 
    52         public float Height { get; set; }
    53     }
    54 
    55     public static class OutputerClass
    56     {
    57         public static string StringClass(object obj)
    58         {
    59             StringBuilder value = new StringBuilder();
    60             if (!obj.GetType().IsClass)
    61                 return value.ToString();
    62             PropertyInfo[] properties = obj.GetType().GetProperties();
    63 
    64             foreach (var property in properties)
    65             {
    66                 DisplayNameAttribute attr = (DisplayNameAttribute)Attribute.GetCustomAttribute(property, typeof(DisplayNameAttribute));
    67                 if (attr != null)
    68                 {
    69                     value.Append(attr.PropertyName);
    70                     value.Append("	");
    71                     value.Append(property.GetValue(obj, null));
    72                     value.Append("
    
    ");
    73                 }
    74             }
    75 
    76             return value.ToString();
    77         }
    78     }
    79 
    80     //可以用attributeUsage声明属性应用的范围,可以多选,多选的时候|运算即可
    81     [AttributeUsage(AttributeTargets.Property | AttributeTargets.Field, Inherited = false)]
    82     [Conditional("Specify")]
    83     public class DisplayNameAttribute : Attribute
    84     {
    85         public string PropertyName { get; set; }
    86 
    87         public DisplayNameAttribute()
    88         { }
    89 
    90         public DisplayNameAttribute(string propertyName)
    91         {
    92             this.PropertyName = propertyName;
    93         }
    94     }
    95 
    96     [Conditional("UnSpecify")]
    97     public class TestDemoAttribute : Attribute
    98     { }
    99 }
    实例

     

     

  • 相关阅读:
    简明Python3教程 12.问题解决
    简明Python3教程 11.数据结构
    【SPOJ 694】Distinct Substrings
    【codeforces Manthan, Codefest 17 C】Helga Hufflepuff's Cup
    【CF Manthan, Codefest 17 B】Marvolo Gaunt's Ring
    【CF Manthan, Codefest 17 A】Tom Riddle's Diary
    【SPOJ 220】 PHRASES
    【POJ 3261】Milk Patterns
    【POJ 3294】Life Forms
    【POJ 1226】Substrings
  • 原文地址:https://www.cnblogs.com/anthonyBlog/p/3173922.html
Copyright © 2011-2022 走看看