Megjegyzés
Az oldalhoz való hozzáféréshez engedély szükséges. Megpróbálhat bejelentkezni vagy módosítani a címtárat.
Az oldalhoz való hozzáféréshez engedély szükséges. Megpróbálhatja módosítani a címtárat.
Az attribútumok lehetővé teszik az információk deklaratív módon való társítását a kódhoz. Emellett olyan újrafelhasználható elemet is biztosíthatnak, amely különböző célokra alkalmazható. Fontolja meg a ObsoleteAttribute. Alkalmazható osztályokra, szerkezetekre, metódusokra, konstruktorokra stb. Deklarálja, hogy az elem elavult. Ezután a C#-fordítón múlik, hogy megkeresse ezt az attribútumot, és végrehajtson néhány műveletet válaszként.
Ebben az oktatóanyagban megtudhatja, hogyan adhat hozzá attribútumokat a kódhoz, hogyan hozhat létre és használhat saját attribútumokat, és hogyan használhatja a .NET-be beépített attribútumokat.
Előfeltételek
Be kell állítania a gépet a .NET futtatására. A telepítési utasításokat a .NET Letöltések oldalán találja. Ezt az alkalmazást Windows, Ubuntu Linux, macOS vagy Docker-tárolóban is futtathatja. Telepítenie kell a kedvenc kódszerkesztőt. Az alábbi leírások a Visual Studio Code-ot használják, amely nyílt forráskódú, platformfüggetlen szerkesztő. Azonban bármilyen eszközt használhat, amely kényelmes az Ön számára.
Az alkalmazás létrehozása
Most, hogy telepítette az összes eszközt, hozzon létre egy új .NET-konzolalkalmazást. A parancssori generátor használatához hajtsa végre a következő parancsot a kedvenc shell (parancsértelmező) programjában:
dotnet new console
Ez a parancs csupasz .NET-projektfájlokat hoz létre. Futtassa dotnet restore
a projekt fordításához szükséges függőségek visszaállítását.
Nem kell futtatnia dotnet restore
, mert az összes olyan parancs implicit módon fut, amely visszaállítást igényel, például dotnet new
, dotnet build
, dotnet run
, dotnet test
, dotnet publish
és dotnet pack
. Az implicit visszaállítás letiltásához használja a --no-restore
lehetőséget.
A dotnet restore
parancs továbbra is hasznos bizonyos esetekben, amikor a explicit visszaállításnak van értelme, például folyamatos integrációs buildeket az Azure DevOps Services vagy olyan buildrendszerekben, amelyeknek explicit módon kell szabályozni a visszaállítást.
További információ a NuGet-hírcsatornák kezeléséről: dotnet restore
dokumentáció.
A program végrehajtásához használja a következőt dotnet run
: . A konzolon a "Hello, World" kimenetnek kell megjelennie.
Attribútumok hozzáadása a kódhoz
A C#-ban az attribútumok az alaposztálytól Attribute
öröklő osztályok. Minden olyan osztály, amelytől öröklődik Attribute
, egyfajta "címkeként" használható más kódrészleteken. Van például egy úgynevezett attribútum ObsoleteAttribute
. Ez az attribútum azt jelzi, hogy a kód elavult, és nem szabad többé használni. Ezt az attribútumot például szögletes zárójelek használatával helyezheti el egy osztályban.
[Obsolete]
public class MyClass
{
}
Bár az osztály neve ObsoleteAttribute
, csak [Obsolete]
-t kell használni a kódban. A legtöbb C#-kód ezt az egyezményt követi. Ha úgy dönt, használhatja a teljes nevet [ObsoleteAttribute]
.
Ha elavultként jelöl meg egy osztályt, érdemes információt adni arról, hogy miért elavult, és/vagy mit érdemes használni helyette. Ennek a magyarázatnak a megadásához sztringparamétert kell megadnia az Elavult attribútumhoz.
[Obsolete("ThisClass is obsolete. Use ThisClass2 instead.")]
public class ThisClass
{
}
A sztringet argumentumként adják át egy ObsoleteAttribute
konstruktornak, mintha ezt írnánk: var attr = new ObsoleteAttribute("some string")
.
Az attribútumkonstruktor paraméterei egyszerű típusokra/literálokra korlátozódnak: bool, int, double, string, Type, enums, etc
és az ilyen típusú tömbökre.
Kifejezés vagy változó nem használható. Szabadon használhat pozíciós vagy elnevezett paramétereket.
Saját attribútum létrehozása
Attribútumot úgy hozhat létre, hogy definiál egy új osztályt, amely az Attribute
alaposztálytól öröklődik.
public class MySpecialAttribute : Attribute
{
}
A korábbi kód segítségével attribútumként használhatja a [MySpecial]
(vagy [MySpecialAttribute]
) elemeket a kódbázis más részein.
[MySpecial]
public class SomeOtherClass
{
}
A .NET alaposztálytár attribútumai, mint például ObsoleteAttribute
, bizonyos viselkedéseket váltanak ki a fordítóprogramban. A létrehozott attribútumok azonban csak metaadatokként viselkednek, és nem eredményeznek semmilyen kódot az attribútumosztályon belül. Önön múlik, hogy az adott metaadatokat a kód más részein hajtja végre.
Itt van egy buktató, amire figyelni kell. Ahogy korábban említettük, attribútumok használatakor csak bizonyos típusok adhatóak át argumentumként. Attribútumtípus létrehozásakor azonban a C#-fordító nem akadályozza meg ezen paraméterek létrehozását. Az alábbi példában létrehozott egy attribútumot egy megfelelően lefordított konstruktorral.
public class GotchaAttribute : Attribute
{
public GotchaAttribute(Foo myClass, string str)
{
}
}
Ezt a konstruktort azonban nem használhatja attribútumszintaxissal.
[Gotcha(new Foo(), "test")] // does not compile
public class AttributeFail
{
}
Az előző kód fordítóhibát okoz, például Attribute constructor parameter 'myClass' has type 'Foo', which is not a valid attribute parameter type
Attribútumhasználat korlátozása
Az attribútumok a következő "célokon" használhatók. Az előző példák az osztályokon mutatják be őket, de a következőkkel is használhatók:
- Összeszerelés
- Osztály
- Konstruktor
- Képviselő
- Enumeráció
- Esemény
- szakterület
- GenerikusParaméter
- Interfész
- Metódus
- Modul
- Paraméter
- Ingatlan
- ReturnValue
- Struktúra
Attribútumosztály létrehozásakor a C# alapértelmezés szerint lehetővé teszi az attribútum használatát bármely lehetséges attribútum-célon. Ha bizonyos célokra szeretné korlátozni az attribútumot, ezt az AttributeUsageAttribute
attribútumosztályon keresztül teheti meg. Igen, egy tulajdonság egy másik tulajdonságban!
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct)]
public class MyAttributeForClassAndStructOnly : Attribute
{
}
Ha a fenti attribútumot olyanra próbálja helyezni, amely nem osztály vagy szerkezet, akkor egy fordítóhiba jelenik meg, például 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()
{ }
}
Kódelemhez csatolt attribútumok használata
Az attribútumok metaadatként működnek. Külső erő nélkül nem csinálnak semmit.
Az attribútumok megkereséséhez és az azokra való reagáláshoz reflexióra van szükség. A reflexió lehetővé teszi, hogy olyan kódot írjon C# nyelven, amely más kódot vizsgál. Használhatja például a Reflectiont egy osztály adatainak lekéréséhez (a kód elején adja hozzá using System.Reflection;
):
TypeInfo typeInfo = typeof(MyClass).GetTypeInfo();
Console.WriteLine("The assembly qualified name of MyClass is " + typeInfo.AssemblyQualifiedName);
Ez a következőhöz hasonlót nyomtat: The assembly qualified name of MyClass is ConsoleApplication.MyClass, attributes, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null
Miután rendelkezik egy TypeInfo
objektummal (vagy egy MemberInfo
, vagy FieldInfo
más objektummal), használhatja a metódust GetCustomAttributes
. Ez a metódus objektumgyűjteményt Attribute
ad vissza. Attribútumtípust is használhat GetCustomAttribute
és megadhat.
Íme egy példa a GetCustomAttributes
használatára egy MemberInfo
példányon MyClass
érdekében (amelyet korábban láttunk, hogy [Obsolete]
attribútum van rajta).
var attrs = typeInfo.GetCustomAttributes();
foreach(var attr in attrs)
Console.WriteLine("Attribute on MyClass: " + attr.GetType().Name);
Ez a konzolra nyomtatja a következőt: Attribute on MyClass: ObsoleteAttribute
. Próbáljon meg más attribútumokat hozzáadni a fájlhoz MyClass
.
Fontos megjegyezni, hogy ezek az Attribute
objektumok lazán vannak példányosítva. Vagyis nincsenek példányosítva, amíg nem használja a GetCustomAttribute
vagy a GetCustomAttributes
elemet. Ők is minden alkalommal példányosítódnak. Ha kétszer egymás után meghívja a GetCustomAttributes
, akkor két különböző ObsoleteAttribute
példányt ad vissza.
Gyakori attribútumok a futtatókörnyezetben
Az attribútumokat számos eszköz és keretrendszer használja. Az NUnit olyan attribútumokat használ, mint a [Test]
és [TestFixture]
, amelyeket az NUnit tesztfuttató használ. ASP.NET MVC az MVC-hez hasonló [Authorize]
attribútumokat használ, és egy műveletszűrő keretrendszert biztosít az MVC-műveletek átfogó problémáinak végrehajtásához.
A PostSharp az attribútumszintaxis használatával engedélyezi a C#-ban a szempontorientált programozást.
Íme néhány figyelemre méltó attribútum a .NET Core alaposztály-kódtárakba:
-
[Obsolete]
. Ezt a fenti példákban használták, és aSystem
névtérben él. Hasznos deklaratív dokumentációt nyújtani egy változó kódbázisról. Egy üzenet sztring formájában is megadható, és egy másik logikai paraméter használatával fordítói figyelmeztetésről fordítói hibára eszkalálható. -
[Conditional]
. Ez az attribútum aSystem.Diagnostics
névtérben található. Ez az attribútum alkalmazható metódusokra (vagy attribútumosztályokra). Sztringet kell átadnia a konstruktornak. Ha ez a sztring nem egyezik meg egy irányelvvel#define
, akkor a C#-fordító eltávolítja az adott metódusra irányuló hívásokat (de magát a metódust nem). Ezt a technikát általában hibakeresési (diagnosztikai) célokra használja. -
[CallerMemberName]
. Ez az attribútum paramétereken használható, és aSystem.Runtime.CompilerServices
névtérben található.CallerMemberName
egy attribútum, amely egy másik metódust hívó metódus nevének injektálására szolgál. Ez egy módja annak, hogy kiküszöbölje a "mágikus sztringeket" az INotifyPropertyChanged implementálása során a különböző felhasználói felületi keretrendszerekben. Példaként:
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
}
}
}
}
A fenti kódban nem kell literális "Name"
sztringet megadnia. A használat CallerMemberName
megakadályozza a elírással kapcsolatos hibákat, és gördülékenyebb újrabontást/átnevezést tesz lehetővé. Az attribútumok deklaratív hatalmat adnak a C#-nak, de a kód metaadat-formája, és nem önállóan működnek.