如何在C#中创build一个自定义属性

我已经尝试了很多次,但仍然无法理解自定义属性的用法(我已经通过了很多链接)。

任何人都可以请解释一个自定义属性与代码的非常基本的例子?

虽然创build自定义属性的代码非常简单,但了解什么是属性非常重要:

属性是编译到你的程序中的元数据。 属性本身不会为类,属性或模块添加任何function,只是数据。 但是,使用reflection,可以利用这些属性来创buildfunction。

因此,我们来看一下Enterprise Library中的 Validation Application Block 。 如果你看一个代码示例,你会看到:

/// <summary> /// blah blah code. /// </summary> [DataMember] [StringLengthValidator(8, RangeBoundaryType.Inclusive, 8, RangeBoundaryType.Inclusive, MessageTemplate = "\"{1}\" must always have \"{4}\" characters.")] public string Code { get; set; } 

从上面的代码片断,人们可能会猜测,代码总是会被validation,每当更改,相应的validation器的规则(在这个例子中,至less有8个字符,最多8个字符)。 但事实是属性什么也不做,只是给元素添加元数据。

但是,企业库有一个Validation.Validate方法,将查看您的对象,并为每个属性,它将检查内容是否违反了该属性通知的规则。

所以,这就是你应该考虑的属性 – 一种向你的代码添加数据的方法,以后可能会被其他方法/类/等使用。

你首先编写一个派生自Attribute的类:

 public class MyCustomAttribute: Attribute { public string SomeProperty { get; set; } } 

那么你可以用这个属性来修饰任何东西(类,方法,属性…):

 [MyCustom(SomeProperty = "foo bar")] public class Foo { } 

最后你会使用reflection来获取它:

 var customAttributes = (MyCustomAttribute[])typeof(Foo).GetCustomAttributes(typeof(MyCustomAttribute), true); if (customAttributes.Length > 0) { var myAttribute = customAttributes[0]; string value = myAttribute.SomeProperty; // TODO: Do something with the value } 

您可以使用AttributeUsage属性限制可以应用此自定义属性的目标types:

 /// <summary> /// This attribute can only be applied to classes /// </summary> [AttributeUsage(AttributeTargets.Class)] public class MyCustomAttribute : Attribute 

重要的事情要了解属性:

  • 属性是元数据。
  • 它们在编译时被烧入程序集,这对你如何设置它们的属性有非常严重的影响。 只有常量(在编译时已知)值才被接受
  • 使自定义属性有意义和用法的唯一方法是使用Reflection 。 所以,如果你不在运行时使用reflection来获取它们,并用自定义属性来装饰某些东西,那么不要期望发生太多的事情。
  • 属性的创build时间是非确定性的。 它们由CLR实例化,你完全无法控制它。

利用/复制达林·季米特洛夫(Darin Dimitrov)的出色反应 ,就是如何访问属性而不是类的自定义属性:

[ Fooclass]的装饰物:

 [MyCustom(SomeProperty = "This is a custom property")] public string MyProperty { get; set; } 

获取它:

 PropertyInfo propertyInfo = typeof(Foo).GetProperty(propertyToCheck); object[] attribute = propertyInfo.GetCustomAttributes(typeof(MyCustomAttribute), true); if (attribute.Length > 0) { MyCustomAttribute myAttribute = (MyCustomAttribute)attribute[0]; string propertyValue = myAttribute.SomeProperty; } 

你可以把它放在一个循环中,并使用reflection来访问Foo类的每个属性的自定义属性。

 foreach (PropertyInfo propertyInfo in Foo.GetType().GetProperties()) { string propertyName = propertyInfo.Name; object[] attribute = propertyInfo.GetCustomAttributes(typeof(MyCustomAttribute), true); // Just in case you have a property without this annotation if (attribute.Length > 0) { MyCustomAttribute myAttribute = (MyCustomAttribute)attribute[0]; string propertyValue = myAttribute.SomeProperty; // TODO: whatever you need with this propertyValue } } 

非常感谢你,达林!