Definiowanie i odczytywanie atrybutów niestandardowych
Atrybuty umożliwiają kojarzenie informacji z kodem w sposób deklaratywny. Mogą również udostępniać element wielokrotnego użytku, który można zastosować do różnych elementów docelowych. Rozważmy element ObsoleteAttribute. Można go stosować do klas, struktur, metod, konstruktorów i nie tylko. Deklaruje, że element jest przestarzały. Następnie do kompilatora języka C# należy wyszukać ten atrybut i wykonać jakąś akcję w odpowiedzi.
Z tego samouczka dowiesz się, jak dodawać atrybuty do kodu, jak tworzyć i używać własnych atrybutów oraz jak używać niektórych atrybutów wbudowanych w platformę .NET.
Wymagania wstępne
Aby uruchomić platformę .NET, musisz skonfigurować maszynę. Instrukcje instalacji można znaleźć na stronie Pliki do pobrania platformy .NET. Tę aplikację można uruchomić w systemach Windows, Ubuntu Linux, macOS lub w kontenerze platformy Docker. Musisz zainstalować ulubiony edytor kodu. Poniższe opisy używają programu Visual Studio Code, który jest edytorem międzyplatformowym typu open source. Można jednak użyć dowolnych narzędzi, z których korzystasz.
Tworzenie aplikacji
Po zainstalowaniu wszystkich narzędzi utwórz nową aplikację konsolową platformy .NET. Aby użyć generatora wiersza polecenia, wykonaj następujące polecenie w ulubionej powłoce:
dotnet new console
To polecenie tworzy pliki projektów .NET bez kości. Uruchom polecenie dotnet restore
, aby przywrócić zależności potrzebne do skompilowania tego projektu.
Nie trzeba uruchamiaćdotnet restore
, ponieważ jest ona uruchamiana niejawnie przez wszystkie polecenia, które wymagają przywrócenia, takie jak dotnet new
, , dotnet build
, dotnet run
dotnet test
, , dotnet publish
, i dotnet pack
. Aby wyłączyć niejawne przywracanie, użyj --no-restore
opcji .
Polecenie dotnet restore
jest nadal przydatne w niektórych scenariuszach, w których jawne przywracanie ma sens, takie jak kompilacje ciągłej integracji w usługach Azure DevOps Services lub w systemach kompilacji, które muszą jawnie kontrolować, kiedy nastąpi przywracanie.
Aby uzyskać informacje na temat zarządzania kanałami informacyjnymi NuGet, zobacz dokumentacjędotnet restore
.
Aby wykonać program, użyj polecenia dotnet run
. Powinny zostać wyświetlone dane wyjściowe "Hello, World" w konsoli.
Dodawanie atrybutów do kodu
W języku C# atrybuty to klasy dziedziczone z klasy bazowej Attribute
. Każda klasa dziedziczona z Attribute
klasy może służyć jako rodzaj "tagu" w innych fragmentach kodu. Na przykład istnieje atrybut o nazwie ObsoleteAttribute
. Ten atrybut sygnalizuje, że kod jest przestarzały i nie powinien już być używany. Ten atrybut należy umieścić na klasie, na przykład przy użyciu nawiasów kwadratowych.
[Obsolete]
public class MyClass
{
}
Chociaż klasa jest wywoływana ObsoleteAttribute
, jest wymagana tylko do użycia [Obsolete]
w kodzie. Większość kodu w języku C# jest zgodna z tą konwencją. Jeśli wybierzesz, możesz użyć pełnej nazwy [ObsoleteAttribute]
.
W przypadku oznaczania klasy przestarzałą warto podać pewne informacje, dlaczego są przestarzałe i/lub co zamiast tego należy użyć. Aby podać to wyjaśnienie, dołącz parametr ciągu do atrybutu Przestarzałe.
[Obsolete("ThisClass is obsolete. Use ThisClass2 instead.")]
public class ThisClass
{
}
Ciąg jest przekazywany jako argument do konstruktora ObsoleteAttribute
, tak jakby pisać var attr = new ObsoleteAttribute("some string")
.
Parametry konstruktora atrybutu są ograniczone do prostych typów/literałów: bool, int, double, string, Type, enums, etc
i tablic tych typów.
Nie można użyć wyrażenia ani zmiennej. Możesz używać parametrów pozycyjnych lub nazwanych.
Tworzenie własnego atrybutu
Atrybut można utworzyć, definiując nową klasę dziedziczą po klasie bazowej Attribute
.
public class MySpecialAttribute : Attribute
{
}
W poprzednim kodzie można użyć [MySpecial]
(lub [MySpecialAttribute]
) jako atrybutu w innym miejscu w bazie kodu.
[MySpecial]
public class SomeOtherClass
{
}
Atrybuty w bibliotece klas bazowych platformy .NET, takie jak ObsoleteAttribute
wyzwalanie niektórych zachowań w kompilatorze. Jednak każdy utworzony atrybut działa tylko jako metadane i nie powoduje wykonania żadnego kodu w klasie atrybutów. To ty musisz wykonywać działania na tych metadanych w innym miejscu w kodzie.
Jest tu "gotcha", aby uważać. Jak wspomniano wcześniej, tylko niektóre typy mogą być przekazywane jako argumenty podczas używania atrybutów. Jednak podczas tworzenia typu atrybutu kompilator języka C# nie powstrzymuje tworzenia tych parametrów. W poniższym przykładzie utworzono atrybut z konstruktorem, który kompiluje się poprawnie.
public class GotchaAttribute : Attribute
{
public GotchaAttribute(Foo myClass, string str)
{
}
}
Nie można jednak użyć tego konstruktora ze składnią atrybutów.
[Gotcha(new Foo(), "test")] // does not compile
public class AttributeFail
{
}
Powyższy kod powoduje błąd kompilatora, taki jak Attribute constructor parameter 'myClass' has type 'Foo', which is not a valid attribute parameter type
Jak ograniczyć użycie atrybutów
Atrybuty mogą być używane w następujących elementach docelowych. Powyższe przykłady pokazują je w klasach, ale mogą być również używane w następujących klasie:
- Zestaw
- Klasa
- Konstruktor
- Delegat
- Wyliczenie
- Zdarzenie
- Pole
- Parametr ogólny
- Interfejs
- Method
- Moduł
- Parametr
- Właściwości
- Returnvalue
- Struktura
Podczas tworzenia klasy atrybutów domyślnie język C# umożliwia używanie tego atrybutu na dowolnym z możliwych obiektów docelowych atrybutów. Jeśli chcesz ograniczyć atrybut do określonych obiektów docelowych, możesz to zrobić przy użyciu klasy atrybutów AttributeUsageAttribute
. To prawda, atrybut atrybutu atrybutu!
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct)]
public class MyAttributeForClassAndStructOnly : Attribute
{
}
Jeśli próbujesz umieścić powyższy atrybut na czymś, co nie jest klasą lub strukturą, zostanie wyświetlony błąd kompilatora, taki jak Attribute 'MyAttributeForClassAndStructOnly' is not valid on this declaration type. It is only valid on 'class, struct' declarations
public class Foo
{
// if the below attribute was uncommented, it would cause a compiler error
// [MyAttributeForClassAndStructOnly]
public Foo()
{ }
}
Jak używać atrybutów dołączonych do elementu kodu
Atrybuty działają jako metadane. Bez jakiejś siły zewnętrznej, nie robią nic.
Aby znaleźć atrybuty i działać na ich podstawie, potrzebne jest odbicie. Emocje ion umożliwia pisanie kodu w języku C#, który analizuje inny kod. Na przykład możesz użyć Emocje ion, aby uzyskać informacje o klasie (dodać using System.Reflection;
na początku kodu):
TypeInfo typeInfo = typeof(MyClass).GetTypeInfo();
Console.WriteLine("The assembly qualified name of MyClass is " + typeInfo.AssemblyQualifiedName);
To drukuje coś takiego jak: The assembly qualified name of MyClass is ConsoleApplication.MyClass, attributes, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null
Po utworzeniu TypeInfo
obiektu (lub MemberInfo
obiektu , FieldInfo
lub innego obiektu) możesz użyć GetCustomAttributes
metody . Ta metoda zwraca kolekcję Attribute
obiektów. Można również użyć GetCustomAttribute
i określić typ atrybutu.
Oto przykład użycia GetCustomAttributes
w wystąpieniu MemberInfo
( MyClass
które widzieliśmy wcześniej ma [Obsolete]
na nim atrybut).
var attrs = typeInfo.GetCustomAttributes();
foreach(var attr in attrs)
Console.WriteLine("Attribute on MyClass: " + attr.GetType().Name);
To drukuje do konsoli: Attribute on MyClass: ObsoleteAttribute
. Spróbuj dodać inne atrybuty do MyClass
elementu .
Należy pamiętać, że te Attribute
obiekty są tworzone leniwie. Oznacza to, że nie są tworzone, dopóki nie zostanie użyta funkcja GetCustomAttribute
lub GetCustomAttributes
. Są one również tworzone za każdym razem. Wywołanie GetCustomAttributes
dwukrotnie w wierszu zwraca dwa różne wystąpienia ObsoleteAttribute
klasy .
Typowe atrybuty w środowisku uruchomieniowym
Atrybuty są używane przez wiele narzędzi i struktur. NUnit używa atrybutów takich jak [Test]
i [TestFixture]
, które są używane przez moduł uruchamiający testy NUnit. ASP.NET MVC używa atrybutów, takich jak [Authorize]
i udostępnia strukturę filtru akcji do wykonywania problemów krzyżowych w akcjach MVC. PostSharp używa składni atrybutów, aby umożliwić programowanie zorientowane na aspekty w języku C#.
Oto kilka godnych uwagi atrybutów wbudowanych w biblioteki klas bazowych platformy .NET Core:
[Obsolete]
. Ten został użyty w powyższych przykładach i znajduje się wSystem
przestrzeni nazw. Warto podać dokumentację deklaratywną dotyczącą zmieniającej się bazy kodu. Komunikat można podać w postaci ciągu, a inny parametr logiczny może służyć do eskalacji z ostrzeżenia kompilatora do błędu kompilatora.[Conditional]
. Ten atrybut znajduje się wSystem.Diagnostics
przestrzeni nazw. Ten atrybut można zastosować do metod (lub klas atrybutów). Należy przekazać ciąg do konstruktora. Jeśli ten ciąg nie jest zgodny z dyrektywą#define
, kompilator języka C# usuwa wszystkie wywołania tej metody (ale nie samej metody). Zazwyczaj ta technika jest używana do debugowania (diagnostyki).[CallerMemberName]
. Ten atrybut może być używany w parametrach i znajduje się wSystem.Runtime.CompilerServices
przestrzeni nazw.CallerMemberName
jest atrybutem używanym do wstrzykiwania nazwy metody wywołującej inną metodę. Jest to sposób na wyeliminowanie "ciągów magicznych" podczas implementowania funkcji INotifyPropertyChanged w różnych strukturach interfejsu użytkownika. Przykład:
public class MyUIClass : INotifyPropertyChanged
{
public event PropertyChangedEventHandler? PropertyChanged;
public void RaisePropertyChanged([CallerMemberName] string propertyName = default!)
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
private string? _name;
public string? Name
{
get { return _name;}
set
{
if (value != _name)
{
_name = value;
RaisePropertyChanged(); // notice that "Name" is not needed here explicitly
}
}
}
}
W powyższym kodzie nie trzeba mieć ciągu literału "Name"
. Użycie CallerMemberName
zapobiega błędom związanym z literówkami, a także zapewnia płynniejszą refaktoryzację/zmianę nazwy. Atrybuty zapewniają deklaratywną moc w języku C#, ale są one meta-data formą kodu i nie działają samodzielnie.
Opinia
https://aka.ms/ContentUserFeedback.
Dostępne już wkrótce: W 2024 r. będziemy stopniowo wycofywać zgłoszenia z serwisu GitHub jako mechanizm przesyłania opinii na temat zawartości i zastępować go nowym systemem opinii. Aby uzyskać więcej informacji, sprawdź:Prześlij i wyświetl opinię dla