我知道属性非常有用。有一些预定义的[Browsable(false)]
属性,例如允许您在属性选项卡中隐藏属性。这是一个解释属性的好问题:.NET中的属性是什么?
您在项目中实际使用的预定义属性(及其名称空间)是什么?
我知道属性非常有用。有一些预定义的[Browsable(false)]
属性,例如允许您在属性选项卡中隐藏属性。这是一个解释属性的好问题:.NET中的属性是什么?
您在项目中实际使用的预定义属性(及其名称空间)是什么?
Answers:
[DebuggerDisplay]
在调试期间将鼠标悬停在Type实例上时,对于快速查看Type的自定义输出很有帮助。例:
[DebuggerDisplay("FirstName={FirstName}, LastName={LastName}")]
class Customer
{
public string FirstName;
public string LastName;
}
这是它在调试器中的外观:
另外,值得一提的是,[WebMethod]
具有CacheDuration
属性集的属性可以避免不必要地执行Web服务方法。
System.Obsolete
我认为,它是框架中最有用的属性之一。发出有关不应再使用的代码的警告的功能非常有用。我喜欢有一种方法可以告诉开发人员不再使用某些东西,并且有一种方法可以解释原因并指出更好/新的方法。
这Conditional attribute
对于调试使用也非常方便。它允许您在代码中添加用于调试目的的方法,这些方法在构建要发布的解决方案时不会被编译。
然后,我发现许多特定于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指出了一些我尚未意识到的事情,但这削弱了我对该属性的热情:它没有指示编译器允许将位组合作为枚举变量的有效值,而编译器无论如何都允许这样做。我的C ++背景显示通过...... 叹
[Flags]
确实比仅仅使用语法糖有更多用途。使用Web服务时,如果SandwichStuff.Cheese | SandwichStuff.Ham | SandwichStuff.Jam
传递类似的值,则序列化/反序列化将不起作用。如果没有该[Flags]
属性,则反序列化器将不知道该值可以是标志的组合。在花了大约两天时间思考为什么我的WCF不能正常工作之后,才以辛苦的方式学习了此方法。
我喜欢[DebuggerStepThrough]
来自System.Diagnostics。
避免单步执行这些单行操作方法或属性(如果您被迫在没有自动属性的早期.Net中工作),这非常方便。将属性放在短方法或属性的获取器或设置器上,即使在调试器中单击“ step into”,您也可以正常运行。
对于它的价值,这里是所有.NET属性的列表。有几百个。
我不认识其他任何人,但是我有一些严肃的RTFM要做!
我的投票是 Conditional
[Conditional("DEBUG")]
public void DebugOnlyFunction()
{
// your code here
}
您可以使用它来添加具有高级调试功能的功能。像一样Debug.Write
,它仅在调试版本中被调用,因此允许您将复杂的调试逻辑封装在程序的主要流程之外。
我总是用DisplayName
,Description
和DefaultValue
属性在我的用户控件,自定义控件,不然我会通过属性编辑网格中任何一类的公共属性。.NET PropertyGrid使用这些标记来格式化名称,描述面板和未设置为默认值的粗体值。
[DisplayName("Error color")]
[Description("The color used on nodes containing errors.")]
[DefaultValue(Color.Red)]
public Color ErrorColor
{
...
}
我只是希望Description
如果找不到XML注释,Visual Studio的IntelliSense将考虑该属性。这样可以避免重复相同的句子两次。
Description
与枚举使用时,直到你..它是最有帮助的我..
[Serializable]
一直使用来与外部数据源(例如xml)或远程服务器之间的对象进行序列化和反序列化。在这里了解更多。
按照霍夫施塔特精神,[Attribute]
属性是非常有用的,因为这是您创建自己的属性的方式。我使用属性而不是接口来实现插件系统,向Enums添加描述,模拟多个调度和其他技巧。
这是有关有趣的属性InternalsVisibleTo的帖子。基本上,它的作用是模仿C ++朋友的访问功能。它非常方便进行单元测试。
internal
公开声明。它在要测试的程序集中是公开的,应该进行单元测试,以便程序集中的其他类可以假定它具有更正功能。如果不对它进行单元测试,则必须在所有使用类中测试其功能。
我发现[DefaultValue]
它非常有用。
我建议[TestFixture]
和[Test]
-从NUnit的库。
代码中的单元测试在重构和整理文档时提供了安全性。
它没有很好的命名,在框架中没有很好的支持,并且不需要参数,但是此属性是不可变类的有用标记:
[ImmutableObject(true)]
ImmutableObjectAttribute
类-至少可以消除该参数。
我喜欢将[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属性使我可以将调用的作用域仅限制在有问题的线程上,从而避免了跨线程访问数据的麻烦问题。
MyContextInformation.Current
以获取堆栈上的活动上下文。在某些情况下,这是一个非常好的概念,我们(我的公司)引擎将其用于许多目的。
所述DebuggerHiddenAttribute其允许避免步骤为代码不应该被调试。
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))
并且包装方法发生错误,则调用堆栈未显示正在调用引发错误的方法的方法。
DesignerSerializationVisibilityAttribute
非常有用 当您在控件或组件上放置运行时属性时,如果您不希望设计人员对其进行序列化,则可以按以下方式使用它:
[DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
public Foo Bar {
get { return baz; }
set { baz = value; }
}
[Browsable(false)]
必须将其隐藏在设计者的用户面前,而这[DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
是必需的,这样它就不会序列化。
只有少数属性获得编译器支持,但是AOP中非常有趣的使用属性:PostSharp使用定制的属性将IL注入方法中,从而允许所有方式的能力... log / trace是简单的示例-但还有其他一些很好的示例是类似自动INotifyPropertyChanged实现(在这里)。
发生并直接影响编译器或运行时的一些事件:
[Conditional("FOO")]
-仅在构建期间定义了“ FOO”符号的情况下,才会调用此方法(包括参数评估)[MethodImpl(...)]
-用于指示一些事情,例如同步,内联[PrincipalPermission(...)]
-用于将安全检查自动注入代码中[TypeForwardedTo(...)]
-用于在程序集之间移动类型而不重建调用方对于通过反射手动检查的事情-我是System.ComponentModel
属性的忠实拥护者;东西喜欢[TypeDescriptionProvider(...)]
,[TypeConverter(...)]
和[Editor(...)]
其可完全改变在数据绑定方案(即动态特性等)的类型的行为。
[TypeConverter(typeof(ExpandableObjectConverter))]
告诉设计器扩展属于(您控制的)类的属性
[Obfuscation]
指示混淆工具对程序集,类型或成员采取指定的操作。(尽管通常您使用的是程序集级别[assembly:ObfuscateAssemblyAttribute(true)]
作为我喜欢的中层开发人员
System.ComponentModel.EditorBrowsableAttribute
让我隐藏属性,以便UI开发人员不会被他们不需要看到的属性所淹没。
System.ComponentModel.BindableAttribute
有些东西不需要数据绑定。同样,减少了UI开发人员需要做的工作。
我也喜欢DefaultValue
劳伦斯·约翰斯顿(Lawrence Johnston)提到的内容。
System.ComponentModel.BrowsableAttribute
并且Flags
经常使用。
我
System.STAThreadAttribute
System.ThreadStaticAttribute
在需要时使用。
顺便说说。对于所有.Net框架开发人员来说,这些都是一样有价值的。
我认为在此提及以下属性也很重要:
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;
}
在我脑海中,这是我在大型项目中实际使用的预定义属性的快速列表(大致按使用频率排序)(约50万个LoC):
标志,可序列化,WebMethod,COMVisible,TypeConverter,条件,ThreadStatic,已过时,InternalsVisibleTo,DebuggerStepThrough。
我通过CodeSmith生成数据实体类,并将属性用于某些验证例程。这是一个例子:
/// <summary>
/// Firm ID
/// </summary>
[ChineseDescription("送样单位编号")]
[ValidRequired()]
public string FirmGUID
{
get { return _firmGUID; }
set { _firmGUID = value; }
}
我得到了一个实用程序类,可以根据附加到数据实体类的属性进行验证。这是代码:
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;
}
}
}
[DeploymentItem("myFile1.txt")]
有关DeploymentItem的MSDN文档
如果要针对文件进行测试或将文件用作测试的输入,则此功能非常有用。
[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() { }
}