最有用的属性

我知道属性是非常有用的。 有一些预定义的例如[Browsable(false)] ,它允许你隐藏属性选项卡中的属性。 这是一个很好的解释属性的问题: 什么是.NET中的属性?

你在项目中实际使用的预定义属性(及其名称空间)是什么?

当在debugging过程中将鼠标hover在types的实例上时, [DebuggerDisplay]对于快速查看Type的自定义输出非常有用。 例:

 [DebuggerDisplay("FirstName={FirstName}, LastName={LastName}")] class Customer { public string FirstName; public string LastName; } 

这是它应该在debugging器中看起来的样子:

替代文字http://serialize.wordpress.com/files/2008/10/temp.jpg

另外,值得一提的是,具有CacheDuration属性集的[WebMethod]属性可以避免不必要的Web服务方法的执行。

在我看来, System.Obsolete是框架中最有用的属性之一。 能够提出有关不再使用的代码的警告是非常有用的。 我喜欢有一种方式来告诉开发者不应该再使用某些东西,并且有办法解释为什么,并指出更好/新的做事方式。

对于debugging使用情况, Conditional attribute也非常方便。 它允许您在代码中添加方法以进行debugging,在构build发布解决scheme时不会进行编译。

然后有很多特定于Web控件的属性,我觉得它们很有用,但是这些属性更具体,并且除了我所发现的服务器控件的开发之外没有任何用途。

[Flags]非常方便。 句法糖是肯定的,但仍然相当不错。

 [Flags] enum SandwichStuff { Cheese = 1, Pickles = 2, Chips = 4, Ham = 8, Eggs = 16, PeanutButter = 32, Jam = 64 }; public Sandwich MakeSandwich(SandwichStuff stuff) { Console.WriteLine(stuff.ToString()); // ... } // ... MakeSandwich(SandwichStuff.Cheese | SandwichStuff.Ham | SandwichStuff.PeanutButter); // produces console output: "Cheese, Ham, PeanutButter" 

Leppie指出了一些我没有意识到的东西,而这些东西反而抑制了我对这个属性的热情:它并没有指示编译器允许位组合作为枚举variables的有效值,编译器允许这样的枚举。 我的C ++背景显示通过… 感叹

我喜欢System.Diagnostics中的[DebuggerStepThrough]

避免进入那些单行无所谓的方法或属性(如果你被迫在没有自动属性的早期.NET中工作),这是非常方便的。 把属性放在一个简短的方法或属性的getter或setter中,即使在debugging器中敲入“step into”,你也可以直接飞行。

对于它的价值,这里是所有.NET属性的列表 。 有几百个。

我不知道其他人,但我有一些严重的RTFM要做!

我的投票将是[Conditional]

 [Conditional("DEBUG")] public void DebugOnlyFunction() { // your code here } 

您可以使用它来添加具有高级debuggingfunction的function; 像Debug.Write ,它只能在debugging版本中调用,所以你可以在你的程序的主stream之外封装复杂的debugging逻辑。

我总是使用DisplayNameDescriptionDefaultValue属性来覆盖我的用户控件,自定义控件或任何我将通过属性网格进行编辑的类。 .NET PropertyGrid使用这些标记来格式化名称,描述面板和未设置为默认值的粗体值。

 [DisplayName("Error color")] [Description("The color used on nodes containing errors.")] [DefaultValue(Color.Red)] public Color ErrorColor { ... } 

如果没有findXML注释,我只希望Visual Studio的智能感知将考虑Description属性。 这将避免重复两次相同的句子。

用于序列化和反序列化外部数据源(例如xml)或来自远程服务器的对象时,始终使用[Serializable] 。 更多关于这里。

在霍夫斯塔德的精神中, [Attribute]属性是非常有用的,因为它是如何创build自己的属性。 我使用属性而不是接口来实现插件系统,向Enums添加描述,模拟多个调度和其他技巧。

这里是关于感兴趣的属性InternalsVisibleTo的文章 。 基本上它是什么模仿C ++的朋友访问function。 它非常方便进行unit testing。

我发现[DefaultValue]非常有用。

我build议[TestFixture][Test] – 从nUnit库。

代码中的unit testing为重构和编写文档提供了安全性。

 [XmlIgnore] 

因为这允许您忽略(在任何xml序列化中)在保存时会导致exception的“父”对象。

它不是很好的名字,在框架中没有得到很好的支持,也不需要参数,但是这个属性是不可变类的一个有用的标记:

 [ImmutableObject(true)] 

我喜欢结合基于线程和堆栈的编程来使用[ThreadStatic]属性。 例如,如果我想要一个值,我想与呼叫序列的其余部分分享,但我想要带外(即在呼叫参数之外),我可能会采用这样的东西。

 class MyContextInformation : IDisposable { [ThreadStatic] private static MyContextInformation current; public static MyContextInformation Current { get { return current; } } private MyContextInformation previous; public MyContextInformation(Object myData) { this.myData = myData; previous = current; current = this; } public void Dispose() { current = previous; } } 

后来在我的代码中,我可以用它来为我的代码下游的人提供带外的上下文信息。 例:

 using(new MyContextInformation(someInfoInContext)) { ... } 

ThreadStatic属性允许我只将调用范围限定在正在讨论的线程中,从而避免线程间数据访问的混乱问题。

DesignerSerializationVisibilityAttribute是非常有用的。 当你把一个运行时属性放在一个控件或组件上,而你不想让devise器序列化它的时候,你可以像这样使用它:

 [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)] public Foo Bar { get { return baz; } set { baz = value; } } 

DebuggerHiddenAttribute允许避免步入不应该被debugging的代码。

 public static class CustomDebug { [DebuggerHidden] public static void Assert(Boolean condition, Func<Exception> exceptionCreator) { ... } } ... // The following assert fails, and because of the attribute the exception is shown at this line // Isn't affecting the stack trace CustomDebug.Assert(false, () => new Exception()); 

此外,它可以防止在堆栈跟踪中显示方法,在使用另一种方法时很有用:

 [DebuggerHidden] public Element GetElementAt(Vector2 position) { return GetElementAt(position.X, position.Y); } public Element GetElementAt(Single x, Single y) { ... } 

如果您现在调用GetElementAt(new Vector2(10, 10))并且在包装方法中发生错误,则调用堆栈不会显示调用引发错误的方法的方法。

我最近一直在使用[DataObjectMethod] 。 它描述了这个方法,所以你可以使用你的类与ObjectDataSource(或其他控件)。

 [DataObjectMethod(DataObjectMethodType.Select)] [DataObjectMethod(DataObjectMethodType.Delete)] [DataObjectMethod(DataObjectMethodType.Update)] [DataObjectMethod(DataObjectMethodType.Insert)] 

更多信息

只有less数属性得到编译器支持,但AOP中有一个非常有趣的属性用法: PostSharp使用你的定制属性来将IL注入方法,允许所有方式的能力… log / trace是简单的例子 – 但其他一些很好的例子是像自动INotifyPropertyChanged实现( 这里 )的东西。

一些发生并直接影响编译器或运行时

  • [Conditional("FOO")] – 只有在构build期间定义了“FOO”符号时,才会调用此方法(包括参数评估)
  • [MethodImpl(...)] – 用于表示一些东西,如同步,内联
  • [PrincipalPermission(...)] – 用于自动将安全检查注入代码
  • [TypeForwardedTo(...)] – 用于在组件之间移动types而不重build调用者

对于通过reflection手动检查的东西 – 我是System.ComponentModel属性的忠实粉丝; 例如[TypeDescriptionProvider(...)][TypeConverter(...)][Editor(...)] ,它们可以完全改变数据绑定场景中types的行为(即dynamic属性等)。

如果我要做一个代码覆盖爬行,我认为这两个将是顶部:

  [Serializable] [WebMethod] 

在我们目前的项目中,我们使用

 [ComVisible(false)] 

它控制个人pipe理的types或成员或程序集中的所有types对COM的可访问性。

更多信息

 [TypeConverter(typeof(ExpandableObjectConverter))] 

告诉devise师扩展属性(你的控制权)

 [Obfuscation] 

指示混淆工具为组件,types或成员采取指定的操作。 (虽然通常使用程序集级别[assembly:ObfuscateAssemblyAttribute(true)]

我使用最多的属性是与XML序列化相关的属性。

XmlRoot

XmlElement

XmlAttribute

等等…

做任何快速和肮脏的XMLparsing或序列化非常有用。

成为我喜欢的中间层开发人员

System.ComponentModel.EditorBrowsableAttribute允许我隐藏属性,以便UI开发人员不会被不需要看到的属性覆盖。

System.ComponentModel.BindableAttribute有些东西不需要数据绑定。 再一次,减less了UI开发者需要做的工作。

我也喜欢Lawrence Johnston提到的DefaultValue

System.ComponentModel.BrowsableAttributeFlags定期使用。

我需要时使用System.STAThreadAttribute System.ThreadStaticAttribute

顺便一提。 对于.Net框架开发人员来说,这些都是有价值的。

在我的头顶,这里是一个快速列表,大致按使用频率sorting,我预先定义的属性在一个大项目中使用(〜500k LoCs):

Flags,Serializable,WebMethod,COMVisible,TypeConverter,有条件的,ThreadStatic,已过时,InternalsVisibleTo,DebuggerStepThrough。

[EditorBrowsable(EditorBrowsableState.Never)]允许您隐藏智能感知的属性和方法,如果该项目不在您的解决scheme。 非常有助于隐藏stream畅接口的无效stream。 你想多久GetHashCode()或Equals()?

对于MVC [ActionName("Name")]允许您使用相同的方法签名获取Get操作和Post操作,或者在操作名称中使用破折号,否则在不为其创build路由的情况下将无法使用破折号。

[DeploymentItem("myFile1.txt")] 部署项目上的MSDN文档

如果您正在testing某个文件或将该文件用作testing的input,则这非常有用。

我认为这里重要的是,下面的属性也是非常重要的:

 STAThreadAttribute 

指示应用程序的COM线程模型是单线程单元(STA)。

例如,在Windows窗体应用程序中使用此属性:

 static class Program { /// <summary> /// The main entry point for the application. /// </summary> [STAThread] static void Main() { Application.EnableVisualStyles(); Application.SetCompatibleTextRenderingDefault(false); Application.Run(new Form1()); } } 

并且 …

 SuppressMessageAttribute 

禁止报告特定的静态分析工具规则违规,允许对单个代码工件进行多重抑制。

例如:

 [SuppressMessage("Microsoft.Performance", "CA1801:ReviewUnusedParameters", MessageId = "isChecked")] [SuppressMessage("Microsoft.Performance", "CA1804:RemoveUnusedLocals", MessageId = "fileIdentifier")] static void FileNode(string name, bool isChecked) { string fileIdentifier = name; string fileName = name; string version = String.Empty; } 

[System.Security.Permissions.PermissionSetAttribute]允许将PermissionSet的安全操作应用于使用声明性安全的代码。

 // usage: public class FullConditionUITypeEditor : UITypeEditor { // The immediate caller is required to have been granted the FullTrust permission. [PermissionSetAttribute(SecurityAction.LinkDemand, Name = "FullTrust")] public FullConditionUITypeEditor() { } } 

我通过CodeSmith生成数据实体类,并使用某些validation例程的属性。 这里是一个例子:

 /// <summary> /// Firm ID /// </summary> [ChineseDescription("送样单位编号")] [ValidRequired()] public string FirmGUID { get { return _firmGUID; } set { _firmGUID = value; } } 

我有一个工具类来根据附加到数据实体类的属性进行validation。 这里是代码:

 namespace Reform.Water.Business.Common { /// <summary> /// Validation Utility /// </summary> public static class ValidationUtility { /// <summary> /// Data entity validation /// </summary> /// <param name="data">Data entity object</param> /// <returns>return true if the object is valid, otherwise return false</returns> public static bool Validate(object data) { bool result = true; PropertyInfo[] properties = data.GetType().GetProperties(); foreach (PropertyInfo p in properties) { //Length validatioin Attribute attribute = Attribute.GetCustomAttribute(p,typeof(ValidLengthAttribute), false); if (attribute != null) { ValidLengthAttribute validLengthAttribute = attribute as ValidLengthAttribute; if (validLengthAttribute != null) { int maxLength = validLengthAttribute.MaxLength; int minLength = validLengthAttribute.MinLength; string stringValue = p.GetValue(data, null).ToString(); if (stringValue.Length < minLength || stringValue.Length > maxLength) { return false; } } } //Range validation attribute = Attribute.GetCustomAttribute(p,typeof(ValidRangeAttribute), false); if (attribute != null) { ValidRangeAttribute validRangeAttribute = attribute as ValidRangeAttribute; if (validRangeAttribute != null) { decimal maxValue = decimal.MaxValue; decimal minValue = decimal.MinValue; decimal.TryParse(validRangeAttribute.MaxValueString, out maxValue); decimal.TryParse(validRangeAttribute.MinValueString, out minValue); decimal decimalValue = 0; decimal.TryParse(p.GetValue(data, null).ToString(), out decimalValue); if (decimalValue < minValue || decimalValue > maxValue) { return false; } } } //Regex validation attribute = Attribute.GetCustomAttribute(p,typeof(ValidRegExAttribute), false); if (attribute != null) { ValidRegExAttribute validRegExAttribute = attribute as ValidRegExAttribute; if (validRegExAttribute != null) { string objectStringValue = p.GetValue(data, null).ToString(); string regExString = validRegExAttribute.RegExString; Regex regEx = new Regex(regExString); if (regEx.Match(objectStringValue) == null) { return false; } } } //Required field validation attribute = Attribute.GetCustomAttribute(p,typeof(ValidRequiredAttribute), false); if (attribute != null) { ValidRequiredAttribute validRequiredAttribute = attribute as ValidRequiredAttribute; if (validRequiredAttribute != null) { object requiredPropertyValue = p.GetValue(data, null); if (requiredPropertyValue == null || string.IsNullOrEmpty(requiredPropertyValue.ToString())) { return false; } } } } return result; } } }