Answers:
元数据。有关您的对象/方法/属性的数据。
例如,我可以声明一个名为:DisplayOrder的属性,以便可以轻松控制应在UI中显示的顺序属性。然后,我可以将其附加到类上并编写一些GUI组件,以提取属性并适当地对UI元素进行排序。
public class DisplayWrapper
{
private UnderlyingClass underlyingObject;
public DisplayWrapper(UnderlyingClass u)
{
underlyingObject = u;
}
[DisplayOrder(1)]
public int SomeInt
{
get
{
return underlyingObject .SomeInt;
}
}
[DisplayOrder(2)]
public DateTime SomeDate
{
get
{
return underlyingObject .SomeDate;
}
}
}
从而确保在使用自定义GUI组件时,始终在SomeDate之前显示SomeInt。
但是,您将看到它们在直接编码环境之外最常用。例如,Windows Designer广泛使用它们,因此它知道如何处理自定义对象。像这样使用BrowsableAttribute:
[Browsable(false)]
public SomeCustomType DontShowThisInTheDesigner
{
get{/*do something*/}
}
例如,告诉设计人员不要在设计时在“属性”窗口的可用属性中列出该属性。
您可能还使用它们生成代码,预编译操作(如后夏普)或运行时操作如Reflection.Emit的。例如,您可以编写一些用于概要分析的代码,以透明方式包装代码进行的每个调用并对其计时。您可以通过放置在特定方法上的属性来“选择退出”计时。
public void SomeProfilingMethod(MethodInfo targetMethod, object target, params object[] args)
{
bool time = true;
foreach (Attribute a in target.GetCustomAttributes())
{
if (a.GetType() is NoTimingAttribute)
{
time = false;
break;
}
}
if (time)
{
StopWatch stopWatch = new StopWatch();
stopWatch.Start();
targetMethod.Invoke(target, args);
stopWatch.Stop();
HandleTimingOutput(targetMethod, stopWatch.Duration);
}
else
{
targetMethod.Invoke(target, args);
}
}
声明它们很容易,只需创建一个从Attribute继承的类即可。
public class DisplayOrderAttribute : Attribute
{
private int order;
public DisplayOrderAttribute(int order)
{
this.order = order;
}
public int Order
{
get { return order; }
}
}
请记住,当您使用属性时,可以省略后缀“ attribute”,编译器将为您添加该属性。
注意:属性本身不会做任何事情-需要使用它们的一些其他代码。有时已经为您编写了该代码,但有时您必须自己编写。例如,C#编译器关心某些框架,某些框架使用某些框架(例如,在加载程序集时,NUnit在类上查找[TestFixture],在测试方法上查找[Test])。
因此,在创建自己的自定义属性时,请注意它根本不会影响代码的行为。您需要编写另一部分(通过反射)检查属性并对其进行操作。
到目前为止,很多人都回答了,但没有人提及。
属性与反射一起大量使用。反思已经相当缓慢。
这是非常值得的标记您的自定义属性为sealed
班提高自己的运行时性能。
考虑在何处使用这样的属性,并为您的属性(!)指明属性,也是一个好主意AttributeUsage
。可用属性用法列表可能会让您感到惊讶:
AttributeUsage属性是AttributeUsage属性签名的一部分也是很酷的。循环依赖的哇!
[AttributeUsageAttribute(AttributeTargets.Class, Inherited = true)]
public sealed class AttributeUsageAttribute : Attribute
属性是用于标记类的一种元数据。例如,这通常在WinForms中用于从工具栏隐藏控件,但可以在自己的应用程序中实现,以使不同类的实例以特定方式运行。
首先创建一个属性:
[AttributeUsage(AttributeTargets.Class, AllowMultiple=false, Inherited=true)]
public class SortOrderAttribute : Attribute
{
public int SortOrder { get; set; }
public SortOrderAttribute(int sortOrder)
{
this.SortOrder = sortOrder;
}
}
所有属性类必须带有后缀“ Attribute”才能有效。
完成此操作后,创建一个使用该属性的类。
[SortOrder(23)]
public class MyClass
{
public MyClass()
{
}
}
现在,您可以SortOrderAttribute
通过执行以下操作来检查特定的类(如果有):
public class MyInvestigatorClass
{
public void InvestigateTheAttribute()
{
// Get the type object for the class that is using
// the attribute.
Type type = typeof(MyClass);
// Get all custom attributes for the type.
object[] attributes = type.GetCustomAttributes(
typeof(SortOrderAttribute), true);
// Now let's make sure that we got at least one attribute.
if (attributes != null && attributes.Length > 0)
{
// Get the first attribute in the list of custom attributes
// that is of the type "SortOrderAttribute". This should only
// be one since we said "AllowMultiple=false".
SortOrderAttribute attribute =
attributes[0] as SortOrderAttribute;
// Now we can get the sort order for the class "MyClass".
int sortOrder = attribute.SortOrder;
}
}
}
如果您想了解更多有关此的信息,可以随时查看MSDN,它具有很好的描述。
希望这对您有所帮助!
属性是一个包含一些功能的类,您可以将这些功能应用于代码中的对象。要创建一个类,请创建一个继承自System.Attribute的类。
至于它们的优点……它们几乎有无限的用途。
属性就像应用于类,方法或程序集的元数据。
它们对许多事物都有好处(调试器可视化,将事物标记为过时,将事物标记为可序列化,列表无穷)。
创建自己的自定义项很容易。从这里开始:
http://msdn.microsoft.com/zh-CN/library/sw480ze8(VS.71).aspx
在我目前正在从事的项目中,有一组各种口味的UI对象,以及一个编辑器,用于将这些对象组合起来以创建供主应用程序使用的页面,有点像DevStudio中的表单设计器。这些对象存在于它们自己的程序集中,并且每个对象都是派生自UserControl
并具有自定义属性的类。此属性的定义如下:
[AttributeUsage (AttributeTargets::Class)]
public ref class ControlDescriptionAttribute : Attribute
{
public:
ControlDescriptionAttribute (String ^name, String ^description) :
_name (name),
_description (description)
{
}
property String ^Name
{
String ^get () { return _name; }
}
property String ^Description
{
String ^get () { return _description; }
}
private:
String
^ _name,
^ _description;
};
我将其应用于这样的类:
[ControlDescription ("Pie Chart", "Displays a pie chart")]
public ref class PieControl sealed : UserControl
{
// stuff
};
这是以前的海报所说的。
要使用该属性,编辑器具有一个Generic::List <Type>
包含控件类型的。有一个列表框,用户可以将其从页面上拖放到页面上以创建控件的实例。要填充列表框,请获取ControlDescriptionAttribute
控件的并在列表中填写一个条目:
// done for each control type
array <Object ^>
// get all the custom attributes
^attributes = controltype->GetCustomAttributes (true);
Type
// this is the one we're interested in
^attributetype = ECMMainPageDisplay::ControlDescriptionAttribute::typeid;
// iterate over the custom attributes
for each (Object ^attribute in attributes)
{
if (attributetype->IsInstanceOfType (attribute))
{
ECMMainPageDisplay::ControlDescriptionAttribute
^description = safe_cast <ECMMainPageDisplay::ControlDescriptionAttribute ^> (attribute);
// get the name and description and create an entry in the list
ListViewItem
^item = gcnew ListViewItem (description->Name);
item->Tag = controltype->Name;
item->SubItems->Add (description->Description);
mcontrols->Items->Add (item);
break;
}
}
注意:以上是C ++ / CLI,但转换为C#并不难(是的,我知道,C ++ / CLI是可憎的,但这是我必须使用的:-()
您可以将属性放在大多数事物上,并且有很多预定义的属性。上面提到的编辑器还在属性上寻找自定义属性,这些属性描述了属性以及如何对其进行编辑。
一旦有了完整的想法,您会想知道没有它们的生活。
您可以使用自定义属性作为在子类中定义标签值的简单方法,而不必为每个子类一遍又一遍地编写相同的代码。我遇到了约翰·沃特斯(John Waters)一个很好的简洁示例,它讲述了如何在自己的代码中定义和使用自定义属性。
在http://msdn.microsoft.com/zh-cn/library/aa288454(VS.71).aspx上有一个教程