.NET中的属性是什么?它们有什么作用?我该如何创建自己的属性?
元数据。关于你的对象/方法/属性的数据。
例如,我可以声明一个名为:DisplayOrder 的特性(attribute),这样我就可以轻松控制属性在 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组件时,确保SomeInt始终在SomeDate之前显示。
然而,你会发现它们最常用于直接编码环境之外。例如,Windows Designer广泛使用它们以便知道如何处理定制的对象。可以这样使用BrowsableAttribute:
[Browsable(false)]
public SomeCustomType DontShowThisInTheDesigner
{
get{/*do something*/}
}
告诉设计人员在设计时不要在属性窗口中列出此属性,例如。
您也可以将它们用于代码生成、预编译操作(例如Post-Sharp)或运行时操作,如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
属性也是AttriuteUsage
签名的一部分,这很酷!哇,循环依赖!
[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,该网站提供了相当不错的描述。
希望这可以帮助到您!
在我目前正在从事的项目中,有一组各种类型的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;
}
}
属性是一个类,它包含一些功能,可以应用于代码中的对象。要创建一个属性,请创建一个从System.Attribute继承的类。
至于它们的好处...几乎有无限多种用途。
属性就像应用于类、方法或程序集的元数据。
它们非常适合各种各样的功能(调试器可视化、将事物标记为过时、将事物标记为可序列化等等)。
创建您自己的自定义属性易如反掌。请从这里开始:
http://msdn.microsoft.com/zh-cn/library/sw480ze8(VS.71).aspx
属性基本上是您想要附加到您的类型(类、方法、事件、枚举等)的数据位。
其想法是在运行时,某些其他类型/框架/工具将查询您的类型以获取属性中的信息并对其进行操作。
例如,Visual Studio可以查询第三方控件上的属性,以确定控件的哪些属性应在设计时间的属性窗格中显示。
属性还可以用于面向方面的编程,在运行时根据修饰它们的属性注入/操作对象,并向对象添加验证、日志记录等,而不影响对象的业务逻辑。
attribute
并按 [TAB] 键。它会展开为一个新属性的模板。