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 }
    实例

     

     

  • 相关阅读:
    [转]在 javascript 按键事件中,按键值的对照表
    表达式树(Expression Tree)
    WPF之路——用户控件对比自定义控件UserControl VS CustomControl)
    wpf创建用户控件(计时器控件)
    WPF 命令
    WPF自定义DataGrid分页控件
    WPF ----在UserControl的xaml里绑定依赖属性
    wpf 自定义ListBox
    WPF 自定义NotifyPropertyChanged
    WPF 使用附加属性增加控件属性
  • 原文地址:https://www.cnblogs.com/anthonyBlog/p/3173922.html
Copyright © 2011-2022 走看看