Najbardziej przydatne atrybuty [zamknięte]


784

Wiem, że atrybuty są niezwykle przydatne. Istnieją pewne predefiniowane, takie jak takie, [Browsable(false)]które pozwalają ukryć właściwości na karcie właściwości. Oto dobre pytanie wyjaśniające atrybuty: Co to są atrybuty w .NET?

Jakie są predefiniowane atrybuty (i ich przestrzeń nazw), których faktycznie używasz w swoich projektach?


27
Co za pytanie? , cała strona jest przepełniona pięknymi odpowiedziami ze wspaniałymi wyjaśnieniami. Czytając to, mam doświadczenie, takie jak przeprowadzanie wywiadów z wieloma ekspertami na temat ich poglądów. +100 za pytanie.
Muthu Ganapathy Nathan

Zgadzam się, takie pytania są jednymi z najcenniejszych - sprawia, że ​​SO jest mniej przydatne, gdy się zamyka.
David Thielen,

Odpowiedzi:


669

[DebuggerDisplay]może być naprawdę pomocny, aby szybko zobaczyć niestandardowe wyjście typu, gdy najedziesz myszką na wystąpienie typu podczas debugowania. przykład:

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

Tak powinno to wyglądać w debuggerze:

alternatywny tekst

Warto również wspomnieć, że [WebMethod]atrybut z CacheDurationzestawem właściwości może uniknąć niepotrzebnego wykonania metody usługi sieciowej.


62
Wow, to naprawdę dobrze wiedzieć. Zwykle osiągnąłem to samo, zastępując ToString, ale jest to lepsze.
Brian

17
Uważaj na to, ponieważ gryzie znacznie większą część twojego procesora niż ToString.
Nikola Radosavljević

1
Możesz także użyć tego do wyświetlenia wyniku metod. Może to powodować dość mylące doświadczenie debugowania, jeśli metoda (lub get-property) ma skutki uboczne.
Øyvind Skaar

4
@ NikolaRadosavljević zajmowałby tylko moc procesora podczas debugowania
Nickolay Kondratyev

2
@Nickolay Kondratyev: Nie znam wszystkich tajników, ale możesz zapoznać się z następującymi sprawdzonymi metodami
Nikola Radosavljević

273

System.Obsoletejest, moim zdaniem, jednym z najbardziej użytecznych atrybutów w ramach. Bardzo przydatna jest możliwość ostrzeżenia o kodzie, który nie powinien już być używany. Uwielbiam mieć sposób, aby powiedzieć programistom, że coś nie powinno być dłużej używane, a także mieć sposób, aby wyjaśnić, dlaczego i wskazać lepszy / nowy sposób robienia czegoś.

Jest Conditional attributeto również bardzo przydatne do debugowania. Pozwala na dodawanie do kodu metod do celów debugowania, które nie zostaną skompilowane po zbudowaniu rozwiązania do wydania.

Następnie istnieje wiele atrybutów specyficznych dla Kontrolek WWW, które uważam za przydatne, ale są one bardziej szczegółowe i nie mają żadnego zastosowania poza opracowaniem kontrolek serwera z tego, co znalazłem.


50
Możesz przekazać „true” jako jeden z parametrów do System.Obsolete, co powoduje, że ostrzeżenie staje się błędem, a zatem przerywa kompilację. Oczywiście należy to zrobić po usunięciu wszystkich ostrzeżeń. :)
Adrian Clark

14
Czy po usunięciu wszystkich ostrzeżeń nie byłoby lepiej po prostu usunąć metodę?
Pedro

10
@ Pedro: Czasami nie można tego zrobić ze względu na kompatybilność wsteczną. Jeśli jest prywatny i nieużywany, tak, usuń go.
Fantius

3
@plinth Zgłaszanie wyjątku byłoby złym pomysłem z wielu powodów, ponieważ nr 1 jest głównym powodem korzystania z Obsolete (), abyś mógł nadal kompilować kod podczas pracy w fazie przejściowej. Jeśli nie pozwalasz nikomu wywoływać tej metody, dlaczego po prostu jej nie usunąć?
Dan Herbert

17
@plinth Ma to na celu uniemożliwienie korzystania z metody przez nowy kod. Stary kod pozostanie kompatybilny binarnie, jeśli metoda zostanie oznaczona jako przestarzała, ale przestanie działać po zgłoszeniu wyjątku. Jeśli ktoś używa refleksji, aby ominąć flagę „Obsolte”, to masz gorsze problemy ...
Dan Herbert

204

[Flags]jest całkiem przydatny. Z pewnością cukier syntaktyczny, ale wciąż całkiem przyjemny.

[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 wskazuje na coś, czego nie zdawałem sobie sprawy, a to raczej tłumi mój entuzjazm dla tego atrybutu: nie instruuje kompilatora, aby zezwalał na kombinacje bitów jako prawidłowe wartości zmiennych wyliczeniowych, kompilator pozwala na to niezależnie od wyliczeń. Moje tło w C ++ pokazano przez ... westchnienie


Co dokładnie robi atrybut Flagi?
Andrei Rînea

13
Mam nadzieję, że zdajecie sobie sprawę, że atrybut Flagi powoduje błąd. W ogóle nie jest potrzebny / używany, z wyjątkiem TypeConverter.
leppie

3
@leppie: ToString () również. Ale ... wow. Z jakiegoś powodu spodziewałem się, że zachowanie wyliczeń bez atrybutu będzie takie samo jak w C ++: lub wartości wygenerują liczbę całkowitą (nie można przekazać takiej metody jak metoda oczekująca enum param). Rozumiem teraz, że tak nie jest. Słabe ... ok, enum .NET jest do bani.
Shog9,

2
[Flagi] naprawdę pomaga tylko funkcjom debuggera i .ToString () wiedzieć, że wartość jest potencjalnie kombinacją kilku deklaracji w wyliczeniu. Nie jestem pewien, to może sprawić, że Intellisense pomoże ci efektywniej wykorzystać wyliczanie.
Kenzi

31
[Flags]ma większe zastosowanie niż tylko cukier syntaktyczny. Podczas korzystania z usług sieciowych serializacja / deserializacja nie będzie działać, jeśli SandwichStuff.Cheese | SandwichStuff.Ham | SandwichStuff.Jamzostanie przekazana podobna wartość . Bez [Flags]atrybutu deserializator nie będzie wiedział, że wartość może być kombinacją flag. Nauczyłem się tego na własnej skórze po spędzeniu około dwóch dni na zastanawianiu się, dlaczego mój WCF nie działa.
Anchit

177

Lubię [DebuggerStepThrough]z System.Diagnostics .

Jest to bardzo przydatne, aby uniknąć wchodzenia w te jednowierszowe metody lub właściwości „nic nie rób” (jeśli jesteś zmuszony do pracy we wczesnej wersji .Net bez właściwości automatycznych). Umieść atrybut na krótkiej metodzie lub narzędziu pobierającym lub ustawiającym właściwość, a będziesz latać tuż obok, nawet po wciśnięciu przycisku „wejdź” do debuggera.


5
Tak wiele razy chciałbym wiedzieć o tej nieruchomości
wusher

1
Szkoda tylko, że zerwane są z zamknięciami - więcej informacji na stronie gregbeech.com/blogs/tech/archive/2008/10/17/ ...
Greg Beech,

3
Przydatny również dla każdego kodu WM_Paint, o którym wiesz, że działa :)
Pondidum

@GregBeech Ten adres URL zwraca błąd .NET. Z klasą! :)
smdrager

@smdrager - To musiał być problem tymczasowy, wydaje mi się, że dzisiaj działa.
Greg Beech

135

Oto, co warto, oto lista wszystkich atrybutów .NET . Jest ich kilkaset.

Nie wiem o nikim innym, ale mam poważne RTFM do zrobienia!


33
opublikowana lista dotyczy .net 1.1 oto lista 3.5 msdn.microsoft.com/en-us/library/system.attribute.aspx (trzeba trochę przewinąć w dół)
kay.one

2
Zaktualizowano link w pytaniu. Teraz jest to pełna lista dla 3.5
R. Martinho Fernandes

8
Właściwie to linki do najnowszych, a nie 3.5.
Brian Ortiz

1
Teraz, gdyby tylko lista nie była tylko listą linków, ale nazwą i opisem. No cóż. @BrianOrtiz ma rację. Lista znajduje się w wersji 4.5.
Luminous

Po prostu zmieniasz strukturę, na którą celujesz, u góry, gdzie jest napisane „Inne wersje”.
Novaterata,

129

Mój głos byłby za Conditional

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

Możesz użyć tego, aby dodać funkcję z zaawansowanymi funkcjami debugowania; na przykład Debug.Write, jest wywoływany tylko w kompilacjach debugowania, a zatem pozwala na enkapsulację złożonej logiki debugowania poza głównym przepływem programu.


5
czy to nie to samo, co robienie #if DEBUG?
Neil N,

10
Nieco #if DEBUGOWANE oznacza, że ​​dzwoniący również nie musi go wywoływać, podczas gdy Conditioinal opuszcza połączenie, ale powoduje, że NOP zostaje wyeliminowany w JIT.
Rangoric

23
Ponadto zwykle używasz #if DEBUGOWANEGO przy połączeniach , a [Warunkowego] przy metodach . Jeśli więc wywołasz metodę debugowania 100 razy, wyłączenie jej jest kwestią jednej zmiany kodu, a nie 100.
Steve Cooper

13
Komentarz Rangorica jest subtelnie niepoprawny (przynajmniej dla C #): metoda jest zawarta w postaci niezmodyfikowanej; sama strona połączeń jest pomijana. Ma to kilka implikacji: parametry nie są oceniane, a metoda warunkowa jest zawarta, niezmodyfikowana, w danych wyjściowych kompilatora. Możesz to sprawdzić za pomocą refleksji. msdn.microsoft.com/en-us/library/aa664622.aspx blogs.msdn.com/b/jmstall/archive/2007/10/15/…
Mark Sowul

97

Zawsze używać DisplayName, Descriptiona DefaultValueprzypisuje się właściwości publiczne moich własnych kontroli użytkowników, kontroli lub dowolnej klasy będę edytować poprzez siatkę nieruchomości. Znaczniki te są używane przez .NET PropertyGrid do formatowania nazwy, panelu opisu i pogrubionych wartości, które nie są ustawione na wartości domyślne.

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

Chciałbym tylko, żeby IntelliSense z Visual Studio wziął ten Descriptionatrybut pod uwagę, gdyby nie znaleziono komentarza XML. Pozwoliłoby to uniknąć powtarzania tego samego zdania dwa razy.


3
Mogę uwierzyć nikt wskazał Descriptionaż was .. Jego najbardziej pomocne dla mnie, gdy używana z teksty stałe ..
Nawfal

68

[Serializable]jest używany przez cały czas do serializacji i deserializacji obiektów do i z zewnętrznych źródeł danych, takich jak xml lub ze zdalnego serwera. Więcej o tym tutaj.


W rzeczywistości jest to odniesienie do atrybutu psuedo, ponieważ C # emituje flagę metadanych dla [Serializable], a nie niestandardową instancję atrybutu;)
TraumaPony

1
Chociaż bardzo przydatne [Serializable] jest dalekie od ideału. To wymaga zbyt wiele majsterkowania i prób i błędów, aby uzyskać pożądany rezultat.
shoosh,

Popieram tego buta!
John Bubriski

System.NonSerializedAttribute jest przydatny, jeśli chcesz mieć większą kontrolę nad automatyczną serializacją.
CSharper

Na marginesie chciałbym dodać, że wydajność wbudowanej serializacji .Net jest dość słaba, na przykład o 2 lub 3 rzędy wielkości wolniejsze niż ręcznie wykonany kod.
redcalx,

57

W duchu Hofstadtian ten [Attribute]atrybut jest bardzo przydatny, ponieważ jest to sposób tworzenia własnych atrybutów. Użyłem atrybutów zamiast interfejsów do implementacji systemów wtyczek, dodawania opisów do Enums, symulacji wielu wysyłek i innych sztuczek.


13
Brzmi nieźle! Czy miałbyś coś przeciwko pokazaniu przykładów systemu wtyczek i opisów enum? Obie rzeczy jestem zainteresowany realizacją siebie!
John Bubriski

46

Oto post o interesującym atrybucie InternalsVisibleTo . Zasadniczo to, co robi, naśladuje funkcjonalność dostępu znajomych w C ++. Jest bardzo przydatny do testowania jednostkowego.


7
Czy nie masz na myśli przydatnego do zhakowania testu jednostkowego na czymś, co nie może / nie powinno być testowane?
the_drow

@ therow: Mówisz o „prywatnych akcesoriach”: msdn.microsoft.com/en-us/library/ms184807%28v=vs.80%29.aspx
habakuk

@hakakuk: Nie bardzo. Są przypadki, w których klasy wewnętrzne powinny być narażone na testy jednostkowe, zwykle z powodu złego projektu.
the_drow

2
@the_drow: Nie powiedziałbym, że InternalsVisibleTo jest zły do ​​testowania jednostkowego; możesz tworzyć i testować mniejsze „jednostki”, które nie są widoczne poza twoim projektem (pomaga to w utrzymaniu czystego i małego interfejsu API). Ale jeśli potrzebujesz „prywatnych akcesoriów” do testowania jednostki, prawdopodobnie coś jest nie tak.
habakuk

10
@ thedd Nie zgadzam się z twoim twierdzeniem, które internalnie jest publiczne. Jest publicznie testowany w zespole i powinien być testowany jednostkowo, aby inne klasy w zespole mogły przyjąć jego funkcję korekcji. Jeśli nie przetestujesz go jednostkowo, będziesz musiał przetestować jego funkcje we wszystkich klasach konsumujących.
tvanfosson,


28

Sugerowałbym [TestFixture]i [Test]- z biblioteki nUnit .

Testy jednostkowe w kodzie zapewniają bezpieczeństwo w refaktoryzacji i skodyfikowanej dokumentacji.


26
[XmlIgnore]

ponieważ pozwala to zignorować (w dowolnej serializacji xml) obiekty „nadrzędne”, które w przeciwnym razie spowodowałyby wyjątki podczas zapisywania.


25

Nie jest dobrze nazwany, nie jest dobrze obsługiwany w środowisku i nie powinien wymagać parametru, ale ten atrybut jest przydatnym markerem dla niezmiennych klas:

[ImmutableObject(true)]

6
Według dokumentów, używane tylko w czasie projektowania (niestety).
Hans Ke ING ing

1
Biorąc pod uwagę, że jest to tylko czas projektowania, być może lepiej byłoby stworzyć własną ImmutableObjectAttributeklasę - przynajmniej możesz wyeliminować parametr.
Roy Tinker

25

Lubię używać tego [ThreadStatic]atrybutu w połączeniu z programowaniem opartym na wątkach i stosach. Na przykład, jeśli chcę wartość, którą chcę podzielić z resztą sekwencji wywołania, ale chcę to zrobić poza pasmem (tj. Poza parametrami wywołania), mogę zastosować coś takiego.

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

Później w moim kodzie mogę tego użyć, aby przekazać informacje kontekstowe poza pasmem osobom znajdującym się poniżej mojego kodu. Przykład:

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

Atrybut ThreadStatic pozwala mi zawęzić wywołanie tylko do danego wątku, unikając bałaganu związanego z dostępem do danych w wątkach.


i jak wtedy uzyskać dostęp? Nie rozumiem tutaj sensu twojej próbki użycia. Możesz wytłumaczyć?
Beachwalker

@Beachwalker Current powinien być statyczny, zredagowany teraz. Teraz możesz uzyskać dostęp, MyContextInformation.Currentaby uzyskać aktywny kontekst na stosie. To jest bardzo dobra koncepcja w niektórych przypadkach, nasz silnik (mojej firmy) używa go do wielu celów.
Felix K.

23

DebuggerHiddenAttribute co pozwala na uniknięcie krok do kodu, który nie powinien być debugowane.

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()); 

Zapobiega także wyświetlaniu metod w stosie śledzenia, co jest przydatne, gdy metoda zawiera tylko inną metodę:

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

public Element GetElementAt(Single x, Single y) { ... }

Jeśli teraz wywołujesz, GetElementAt(new Vector2(10, 10))a błąd jest zawijany w metodzie opakowanej, stos wywołań nie pokazuje metody, która wywołuje metodę zgłaszającą błąd.


21

DesignerSerializationVisibilityAttributejest bardzo przydatne. Gdy umieścisz właściwość środowiska wykonawczego w formancie lub komponencie i nie chcesz, aby projektant serializował ją, używasz jej w następujący sposób:

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

4
bardzo przydatne dla komponentów WinForms. używać w połączeniu z [Browsable (false)]
Mark Heath

3
Dobra uwaga - [Browsable(false)]jest wymagana, aby ukryć ją przed użytkownikiem projektanta, gdzie [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]jest wymagana, aby nie została serializowana.
konfigurator

17

Tylko kilka atrybutów jest wspieranych przez kompilator, ale jedno bardzo interesujące użycie atrybutów znajduje się w AOP: PostSharp używa twoich niestandardowych atrybutów do wstrzykiwania IL do metod, pozwalając na wszystkie możliwości ... log / trace są trywialnymi przykładami - ale kilka innych dobrych przykładów są rzeczy takie jak automatyczna implementacja INotifyPropertyChanged ( tutaj ).

Niektóre z nich mają bezpośredni wpływ na kompilator lub środowisko wykonawcze :

  • [Conditional("FOO")] - wywołania tej metody (w tym oceny argumentów) występują tylko wtedy, gdy podczas kompilacji zdefiniowano symbol „FOO”
  • [MethodImpl(...)] - używany do wskazania kilku rzeczy, takich jak synchronizacja, wstawianie
  • [PrincipalPermission(...)] - używane do automatycznego wprowadzania kontroli bezpieczeństwa do kodu
  • [TypeForwardedTo(...)]- służy do przenoszenia typów między złożeniami bez odbudowywania wywołujących

W przypadku rzeczy, które są sprawdzane ręcznie przez odbicie - jestem wielkim fanem System.ComponentModelatrybutów; rzeczy takie jak [TypeDescriptionProvider(...)], [TypeConverter(...)]i [Editor(...)]które mogą całkowicie zmienić zachowanie typów w scenariuszach wiązania danych (tj. właściwości dynamiczne itp.).


15

Gdybym miał wykonać indeksowanie pokrycia kodu, myślę, że te dwa byłyby najlepsze:

 [Serializable]
 [WebMethod]

15
[WebMethod] służy do dekorowania metody ujawnionej w serwisie internetowym. [Serializable] oznacza twoje obiekty, dzięki czemu można je serializować w celach takich jak przekazywanie ich między domenami aplikacji.
Kev

15

I zostały z wykorzystaniem [DataObjectMethod]ostatnio. Opisuje metodę, dzięki której możesz używać swojej klasy z ObjectDataSource (lub innymi kontrolkami).

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

Więcej informacji


12

W naszym obecnym projekcie korzystamy

[ComVisible(false)]

Kontroluje dostępność pojedynczego zarządzanego typu lub elementu lub wszystkich typów w zespole do modelu COM.

Więcej informacji


12
[TypeConverter(typeof(ExpandableObjectConverter))]

Mówi projektantowi, aby rozwinął właściwości, które są klasami (twojej kontroli)

[Obfuscation]

Nakazuje narzędziom zaciemniającym wykonanie określonych działań dla złożenia, typu lub elementu. (Chociaż zwykle używasz poziomu asemblera[assembly:ObfuscateAssemblyAttribute(true)]


1
Zgadłem, ale się myliłem. Atrybut zaciemnienia jest jedynie wskazówką dla obfsucatorów innych firm. Nie powoduje domyślnego zaciemnienia przez kompilator.
Dan Is Fiddling By Firelight

@DanNeely bezpłatny dla użytkowników Visual Studio Pro / Ultimate!
Chris S

4
Jeśli masz na myśli DotFuscator Community Edition, poziom ochrony jest tak niski, że w najlepszym razie ledwo się liczy.
Dan Is Fiddling By Firelight,

@ricovox Dodałem podsumowanie
Chris S

9

Atrybuty, których najczęściej używam, to te związane z serializacją XML.

XmlRoot

XmlElement

XmlAttribute

itp...

Niezwykle przydatny podczas szybkiego i brudnego analizowania lub serializacji XML.


8

Jako programista średniego poziomu lubię

System.ComponentModel.EditorBrowsableAttribute Pozwala mi ukrywać właściwości, aby programista interfejsu użytkownika nie był przytłoczony właściwościami, których nie muszą widzieć.

System.ComponentModel.BindableAttributeNiektóre rzeczy nie muszą być danymi. Ponownie zmniejsza pracę, którą muszą wykonać programiści interfejsu użytkownika.

Podoba mi się także wspomniany DefaultValueprzez Lawrence'a Johnstona.

System.ComponentModel.BrowsableAttributei Flagssą używane regularnie.

Używam w System.STAThreadAttribute System.ThreadStaticAttribute razie potrzeby.

Tak poza tym. I są one tak samo cenne dla wszystkich programistów .NET Framework.


8

[EditorBrowsable(EditorBrowsableState.Never)]pozwala ukryć właściwości i metody przed IntelliSense, jeśli projekt nie jest w twoim rozwiązaniu. Bardzo pomocne w ukrywaniu nieprawidłowych przepływów dla płynnych interfejsów. Jak często chcesz GetHashCode () lub Equals ()?

Dla MVC [ActionName("Name")]pozwala mieć akcję Get i Post z tą samą sygnaturą metody lub użycie myślników w nazwie akcji, co w innym przypadku nie byłoby możliwe bez utworzenia dla niej trasy.


8

Uważam, że należy tutaj wspomnieć, że następujące atrybuty są również bardzo ważne:

STAThreadAttribute 

Wskazuje, że model wątkowania COM dla aplikacji to jedno-wątkowy apartament (STA).

Na przykład ten atrybut jest używany w aplikacjach 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());
    }
}

I również ...

SuppressMessageAttribute

Pomija zgłaszanie naruszenia określonych reguł narzędzia analizy statycznej, umożliwiając wielokrotne pomijanie pojedynczego artefaktu kodu.

Na przykład:

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

Czy STAThread służy do zapobiegania przypadkowemu wydzieleniu się aplikacji podczas uruchamiania?
Luminous

7

Z góry mojej głowy znajduje się krótka lista, z grubsza posortowana według częstotliwości użycia, predefiniowanych atrybutów, których faktycznie używam w dużym projekcie (~ 500 tys. LoC):

Flagi, Serializable, WebMethod, COMVisible, TypeConverter, Conditional, ThreadStatic, Przestarzałe, InternalsVisibleTo, DebuggerStepThrough.


2
+1 dla ThreadStatic, zaskoczony, że nikt o tym nie wspominał, a także dla podejścia statystycznego
staafl

6

Generuję klasę danych za pomocą CodeSmith i używam atrybutów do niektórych procedur sprawdzania poprawności. Oto przykład:

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

Mam klasę narzędziową do sprawdzania poprawności na podstawie atrybutów dołączonych do klasy encji danych. Oto kod:

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


5

[System.Security.Permissions.PermissionSetAttribute] zezwala na stosowanie działań zabezpieczających dla pakietu PermissionSet do kodu przy użyciu deklaratywnych zabezpieczeń.

// usage:
public class FullConditionUITypeEditor : UITypeEditor
{
    // The immediate caller is required to have been granted the FullTrust permission.
    [PermissionSetAttribute(SecurityAction.LinkDemand, Name = "FullTrust")]
    public FullConditionUITypeEditor() { }
}
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.