developer tip

가장 유용한 속성

copycodes 2020. 9. 29. 07:59
반응형

가장 유용한 속성 [닫힘]


속성이 매우 유용하다는 것을 알고 있습니다. [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 ++ 배경을 통해 ... 한숨


나는 [DebuggerStepThrough]System.Diagnostics에서 좋아 합니다.

자동 속성없이 초기 .Net에서 작업해야하는 경우 한 줄로 아무것도하지 않는 메서드 나 속성에 들어 가지 않도록하는 데 매우 유용합니다. 속성을 짧은 메서드 나 속성의 getter 또는 setter에 배치하면 디버거에서 "step into"를 누르더라도 바로 이동할 수 있습니다.


그만한 가치는 여기 에 모든 .NET 속성 목록이 있습니다. 수백이 있습니다.

나는 다른 사람에 대해 잘 모르지만 심각한 RTFM이 있습니다!


내 투표는 [Conditional]

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

이를 사용하여 고급 디버깅 기능이있는 기능을 추가 할 수 있습니다. 와 같이 Debug.Write디버그 빌드에서만 호출되므로 프로그램의 주요 흐름 외부에서 복잡한 디버그 논리를 캡슐화 할 수 있습니다.


저는 항상 사용자 컨트롤, 사용자 지정 컨트롤 또는 속성 표를 통해 편집 할 클래스의 공용 속성에 대해 DisplayName, DescriptionDefaultValue특성을 사용합니다 . 이러한 태그는 .NET PropertyGrid에서 기본값으로 설정되지 않은 이름, 설명 패널 및 굵게 값의 형식을 지정하는 데 사용됩니다.

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

DescriptionXML 주석이없는 경우 Visual Studio의 IntelliSense가 특성을 고려하기를 바랍니다. 같은 문장을 두 번 반복하지 않아도됩니다.


[Serializable]xml과 같은 외부 데이터 소스 나 원격 서버에서 개체를 직렬화 및 역 직렬화하는 데 항상 사용됩니다. 여기에서 더 자세히 알아보세요.


Hofstadtian 정신에서 [Attribute]속성은 자신의 속성을 만드는 방법이기 때문에 매우 유용합니다. 인터페이스 대신 속성을 사용하여 플러그인 시스템을 구현하고, Enum에 설명을 추가하고, 여러 디스패치 및 기타 트릭을 시뮬레이션했습니다.


여기에 흥미로운 속성에 대한 게시물입니다 InternalsVisibleTo는 . 기본적으로 C ++ 친구 액세스 기능을 모방합니다. 단위 테스트에 매우 편리합니다.


나는 [DefaultValue]매우 유용하다는 것을 알았 습니다.


나는 nUnit 라이브러리 에서 제안 [TestFixture]하고 싶습니다 .[Test]

코드의 단위 테스트는 리팩토링 및 코드화 된 문서에서 안전성을 제공합니다.


[XmlIgnore]

이렇게하면 저장할 때 예외를 발생시키는 '부모'객체를 무시할 수 있습니다 (모든 xml 직렬화에서).


이름이 잘 지정되지 않았고 프레임 워크에서 잘 지원되지 않으며 매개 변수가 필요하지도 않지만이 속성은 변경 불가능한 클래스에 유용한 마커입니다.

[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 속성을 사용하면 스레드 간 데이터 액세스의 복잡한 문제를 방지하면서 해당 스레드로만 호출 범위를 지정할 수 있습니다.


디버그해서는 안되는 코드로의 단계를 피할 수 있는 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; }
}

몇 가지 속성 만 컴파일러 지원을 받지만 AOP에서 매우 흥미로운 속성 사용은 다음과 같습니다. PostSharp 는 맞춤형 속성을 사용하여 IL을 메서드에 주입하여 모든 기능을 허용합니다 ... 로그 / 추적은 사소한 예이지만 다른 좋은 예입니다. 자동 INotifyPropertyChanged 구현과 같은 것입니다 ( 여기 ).

컴파일러 또는 런타임에 직접 발생하고 영향을 미치는 일부 :

  • [Conditional("FOO")] -이 메서드에 대한 호출 (인수 평가 포함)은 빌드 중에 "FOO"기호가 정의 된 경우에만 발생합니다.
  • [MethodImpl(...)] -동기화, 인라인과 같은 몇 가지를 나타내는 데 사용
  • [PrincipalPermission(...)] -코드에 보안 검사를 자동으로 삽입하는 데 사용
  • [TypeForwardedTo(...)]- 호출자를 다시 작성하지 않고 어셈블리간에 형식을 이동하는 데 사용됩니다.

리플렉션을 통해 수동으로 확인되는 항목의 경우-나는 System.ComponentModel속성 의 열렬한 팬입니다 . 것들처럼 [TypeDescriptionProvider(...)], [TypeConverter(...)][Editor(...)]어떤 데이터가 완전히 결합 시나리오 (즉, 동적 특성 등)의 형태의 동작을 변경할 수있다.


코드 커버리지 크롤링을 수행한다면 다음 두 가지가 최고라고 생각합니다.

 [Serializable]
 [WebMethod]

나는 [DataObjectMethod]최근 에 사용하고 있습니다. ObjectDataSource (또는 기타 컨트롤)와 함께 클래스를 사용할 수 있도록 메서드를 설명합니다.

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

더 많은 정보


현재 프로젝트에서는

[ComVisible(false)]

개별 관리 형식이나 멤버 또는 어셈블리 내의 모든 형식에 대한 COM 액세스 가능성을 제어합니다.

더 많은 정보


[TypeConverter(typeof(ExpandableObjectConverter))]

디자이너에게 (컨트롤의) 클래스 인 속성을 확장하도록 지시합니다.

[Obfuscation]

난독 화 도구가 어셈블리, 형식 또는 멤버에 대해 지정된 작업을 수행하도록 지시합니다. (일반적으로 어셈블리 수준을 사용하지만[assembly:ObfuscateAssemblyAttribute(true)]


내가 가장 많이 사용하는 속성은 XML 직렬화와 관련된 속성입니다.

XmlRoot

XmlElement

XmlAttribute

기타...

빠르고 더러운 XML 구문 분석 또는 직렬화를 수행 할 때 매우 유용합니다.


내가 좋아하는 중간 계층 개발자

System.ComponentModel.EditorBrowsableAttribute UI 개발자가 볼 필요가없는 속성에 압도되지 않도록 속성을 숨길 수 있습니다.

System.ComponentModel.BindableAttribute일부는 데이터 바인딩이 필요하지 않습니다. 다시 말하지만 UI 개발자가 수행해야하는 작업이 줄어 듭니다.

나는 또한 DefaultValueLawrence Johnston이 언급 한 것을 좋아합니다 .

System.ComponentModel.BrowsableAttribute그리고 Flags정기적으로 사용됩니다.

나는 System.STAThreadAttribute System.ThreadStaticAttribute필요할 때 사용 합니다.

그건 그렇고. I 이것들은 모든 .Net 프레임 워크 개발자에게 똑같이 가치가 있습니다.


[EditorBrowsable(EditorBrowsableState.Never)]프로젝트가 솔루션에없는 경우 IntelliSense에서 속성 및 메서드를 숨길 수 있습니다. 유창한 인터페이스의 잘못된 흐름을 숨기는 데 매우 유용합니다. 얼마나 자주 GetHashCode () 또는 Equals ()를 원하십니까?

MVC의 [ActionName("Name")]경우 동일한 메서드 서명이있는 Get 작업 및 Post 작업을 사용하거나 작업 이름에 대시를 사용할 수 있습니다. 그렇지 않으면 경로를 만들지 않고는 불가능합니다.


머릿속에서 큰 프로젝트 (~ 500k LoC)에서 실제로 사용하는 사전 정의 된 속성에 대한 대략적인 사용 빈도별로 정렬 된 빠른 목록이 있습니다.

Flags, Serializable, WebMethod, COMVisible, TypeConverter, Conditional, ThreadStatic, Obsolete, InternalsVisibleTo, DebuggerStepThrough.


여기서 언급하는 것이 중요하다고 생각합니다. 다음 속성도 매우 중요합니다.

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;
}

[DeploymentItem("myFile1.txt")] DeploymentItem에 대한 MSDN 문서

이것은 파일에 대해 테스트하거나 파일을 테스트의 입력으로 사용하는 경우 매우 유용합니다.


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;
    }
}
}

[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() { }
}

참고 URL : https://stackoverflow.com/questions/144833/most-useful-attributes

반응형