• 设为首页
  • 点击收藏
  • 手机版
    手机扫一扫访问
    迪恩网络手机版
  • 关注官方公众号
    微信扫一扫关注
    迪恩网络公众号

再次深入C#Attribute

原作者: [db:作者] 来自: [db:来源] 收藏 邀请
  • 了解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("\t");
39                 value.Append(property.GetValue(this, null));
40                 value.Append("\n\r");
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("\t");
71                     value.Append(property.GetValue(obj, null));
72                     value.Append("\n\r");
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 }
实例

 

 


鲜花

握手

雷人

路过

鸡蛋
该文章已有0人参与评论

请发表评论

全部评论

专题导读
上一篇:
C#IEnumerable,Lambda表达式和Parallel并行编程的用法发布时间:2022-07-10
下一篇:
c#dappermysqllike参数化发布时间:2022-07-10
热门推荐
阅读排行榜

扫描微信二维码

查看手机版网站

随时了解更新最新资讯

139-2527-9053

在线客服(服务时间 9:00~18:00)

在线QQ客服
地址:深圳市南山区西丽大学城创智工业园
电邮:jeky_zhao#qq.com
移动电话:139-2527-9053

Powered by 互联科技 X3.4© 2001-2213 极客世界.|Sitemap