속성이 매우 유용하다는 것을 알고 있습니다. [Browsable(false)]
속성 탭에서 속성을 숨길 수있는 것과 같은 미리 정의 된 것들이 있습니다 . 다음은 특성을 설명하는 좋은 질문 입니다. .NET의 특성은 무엇입니까?
프로젝트에서 실제로 사용하는 사전 정의 된 속성 (및 네임 스페이스)은 무엇입니까?
속성이 매우 유용하다는 것을 알고 있습니다. [Browsable(false)]
속성 탭에서 속성을 숨길 수있는 것과 같은 미리 정의 된 것들이 있습니다 . 다음은 특성을 설명하는 좋은 질문 입니다. .NET의 특성은 무엇입니까?
프로젝트에서 실제로 사용하는 사전 정의 된 속성 (및 네임 스페이스)은 무엇입니까?
답변:
[DebuggerDisplay]
디버깅하는 동안 Type의 인스턴스 위로 마우스를 가져 가면 Type의 사용자 정의 된 출력을 빠르게 볼 수 있습니다. 예:
[DebuggerDisplay("FirstName={FirstName}, LastName={LastName}")]
class Customer
{
public string FirstName;
public string LastName;
}
이것이 디버거에서 어떻게 보이는지입니다.
또한 속성이 설정된 [WebMethod]
속성 CacheDuration
은 웹 서비스 메서드의 불필요한 실행을 피할 수 있습니다.
System.Obsolete
내 의견으로는 프레임 워크에서 가장 유용한 속성 중 하나입니다. 더 이상 사용해서는 안되는 코드에 대한 경고를 발생시키는 기능은 매우 유용합니다. 나는 개발자에게 무언가를 더 이상 사용해서는 안된다고 말하고, 왜 더 좋은 / 새로운 것을하는 방법을 설명 할 수있는 방법을 갖는 것을 좋아합니다.
는 Conditional attribute
디버그 용도로도 매우 편리합니다. 릴리스 할 솔루션을 빌드 할 때 컴파일되지 않는 디버그 목적으로 코드에 메소드를 추가 할 수 있습니다.
그런 다음 유용하다고 생각되는 웹 컨트롤과 관련된 많은 속성이 있지만 더 구체적이며 내가 찾은 서버 컨트롤 개발 이외의 용도는 없습니다.
[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]
구문 설탕보다 더 많이 사용됩니다. 웹 서비스를 사용하는 동안 같은 값 SandwichStuff.Cheese | SandwichStuff.Ham | SandwichStuff.Jam
이 전달 되면 직렬화 / 역 직렬화가 작동하지 않습니다 . [Flags]
속성이 없으면 deserializer는 값이 플래그의 조합 일 수 있음을 알 수 없습니다. WCF가 작동하지 않는 이유를 생각하는 데 약 이틀을 소비 한 후 어려운 방법을 배웠습니다.
[DebuggerStepThrough]
System.Diagnostics에서 좋아 합니다.
자동 속성없이 초기 .Net에서 작업 해야하는 경우 한 줄 할 일이없는 방법이나 속성으로 들어가는 것을 피하는 데 매우 편리합니다. 속성을 짧은 메서드 나 속성의 getter 또는 setter에 넣으면 디버거에서 "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 또는 원격 서버와 같은 외부 데이터 소스와 객체를 직렬화 및 역 직렬화하는 데 항상 사용됩니다. 자세한 내용은 여기를 참조하십시오.
Hofstadtian 정신에서 [Attribute]
속성은 사용자가 자신의 속성을 만드는 방식이므로 매우 유용합니다. 플러그인 시스템을 구현하고 Enum에 설명을 추가하고 여러 디스패치 및 기타 트릭을 시뮬레이션하기 위해 인터페이스 대신 속성을 사용했습니다.
여기에 흥미로운 속성에 대한 게시물입니다 InternalsVisibleTo는 . 기본적으로 C ++ 친구 액세스 기능을 모방합니다. 단위 테스트에 매우 편리합니다.
internal
공개되지 않은 않습니다. 테스트중인 어셈블리 내에서 공개되며 어셈블리 내의 다른 클래스가 수정 기능을 수행 할 수 있도록 단위 테스트를 받아야합니다. 단위 테스트를하지 않으면 모든 소비 클래스에서 해당 기능을 테스트해야합니다.
나는 [DefaultValue]
매우 유용한 것으로 나타났습니다 .
nUnit 라이브러리 에서 제안 [TestFixture]
하고 싶습니다 .[Test]
코드의 단위 테스트는 리팩토링 및 체계화 된 문서화에서 안전을 제공합니다.
이름이없고 프레임 워크에서 잘 지원되지 않으며 매개 변수가 필요하지 않지만이 속성은 불변 클래스에 유용한 마커입니다.
[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을 메소드에 주입하여 모든 방식의 기능을 허용합니다. 자동 INotifyPropertyChanged 구현 ( here ) 과 같은 것들 입니다.
컴파일러 또는 런타임에 직접 발생하고 영향을 미치는 일부 :
[Conditional("FOO")]
-이 메소드에 대한 호출 (인수 평가 포함)은 빌드 중에 "FOO"기호가 정의 된 경우에만 발생합니다.[MethodImpl(...)]
-동기화, 인라인과 같은 몇 가지를 나타내는 데 사용[PrincipalPermission(...)]
-코드에 보안 검사를 자동으로 주입하는 데 사용[TypeForwardedTo(...)]
- 호출자를 다시 작성하지 않고 어셈블리간에 유형을 이동하는 데 사용리플렉션을 통해 수동으로 확인되는 것들에 대해-나는 System.ComponentModel
속성 의 큰 팬입니다 . 것들처럼 [TypeDescriptionProvider(...)]
, [TypeConverter(...)]
및 [Editor(...)]
어떤 데이터가 완전히 결합 시나리오 (즉, 동적 특성 등)의 형태의 동작을 변경할 수있다.
나는 [DataObjectMethod]
최근 에 사용하고 있습니다. 클래스를 ObjectDataSource (또는 다른 컨트롤)와 함께 사용할 수 있도록 메소드를 설명합니다.
[DataObjectMethod(DataObjectMethodType.Select)]
[DataObjectMethod(DataObjectMethodType.Delete)]
[DataObjectMethod(DataObjectMethodType.Update)]
[DataObjectMethod(DataObjectMethodType.Insert)]
[TypeConverter(typeof(ExpandableObjectConverter))]
디자이너에게 클래스의 속성 인 컨트롤을 확장하도록 지시합니다.
[Obfuscation]
난독 화 도구에 어셈블리, 유형 또는 멤버에 대해 지정된 작업을 수행하도록 지시합니다. (일반적으로 어셈블리 수준을 사용하지만[assembly:ObfuscateAssemblyAttribute(true)]
내가 좋아하는 중간 계층 개발자
System.ComponentModel.EditorBrowsableAttribute
UI 개발자가 볼 필요가없는 속성에 압도되지 않도록 속성을 숨길 수 있습니다.
System.ComponentModel.BindableAttribute
일부는 데이터 바인딩 될 필요가 없습니다. 다시 한 번, UI 개발자가해야 할 작업이 줄어 듭니다.
DefaultValue
로렌스 존스턴이 언급 한 것도 좋아합니다 .
System.ComponentModel.BrowsableAttribute
그리고 Flags
정기적으로 사용됩니다.
System.STAThreadAttribute
System.ThreadStaticAttribute
필요할 때 사용
합니다.
그건 그렇고 나는 이것들이 모든 .Net 프레임 워크 개발자에게 가치가 있습니다.
[EditorBrowsable(EditorBrowsableState.Never)]
프로젝트가 솔루션에없는 경우 IntelliSense에서 속성 및 메서드를 숨길 수 있습니다. 유창한 인터페이스의 잘못된 흐름을 숨기는 데 매우 유용합니다. GetHashCode () 또는 Equals ()를 얼마나 자주 원하십니까?
MVC의 [ActionName("Name")]
경우 동일한 메소드 서명을 가진 Get 조치 및 Post 조치를 갖거나 조치 이름에 대시를 사용할 수 있습니다. 그렇지 않으면 경로를 작성하지 않고는 불가능합니다.
다음 속성도 매우 중요하다는 점을 언급하는 것이 중요합니다.
STAThreadAttribute
응용 프로그램의 COM 스레딩 모델이 단일 스레드 아파트 (STA)임을 나타냅니다.
예를 들어이 특성은 Windows Forms 응용 프로그램에서 사용됩니다.
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;
}
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 Doc
파일에 대해 테스트하거나 파일을 테스트의 입력으로 사용하는 경우에 매우 유용합니다.
[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() { }
}