Ist es möglich, ein Attribut zu erstellen, das mit einer variablen Anzahl von Argumenten initialisiert werden kann?
Beispielsweise:
[MyCustomAttribute(new int[3,4,5])] // this doesn't work
public MyClass ...
Ist es möglich, ein Attribut zu erstellen, das mit einer variablen Anzahl von Argumenten initialisiert werden kann?
Beispielsweise:
[MyCustomAttribute(new int[3,4,5])] // this doesn't work
public MyClass ...
Antworten:
Attribute nehmen ein Array an. Wenn Sie das Attribut steuern, können Sie paramsstattdessen auch Folgendes verwenden (was für Verbraucher besser ist, IMO):
class MyCustomAttribute : Attribute {
public int[] Values { get; set; }
public MyCustomAttribute(params int[] values) {
this.Values = values;
}
}
[MyCustomAttribute(3, 4, 5)]
class MyClass { }
Ihre Syntax für die Array-Erstellung ist zufällig deaktiviert:
class MyCustomAttribute : Attribute {
public int[] Values { get; set; }
public MyCustomAttribute(int[] values) {
this.Values = values;
}
}
[MyCustomAttribute(new int[] { 3, 4, 5 })]
class MyClass { }
Sie können es tun, aber es ist nicht CLS-konform:
[assembly: CLSCompliant(true)]
class Foo : Attribute
{
public Foo(string[] vals) { }
}
[Foo(new string[] {"abc","def"})]
static void Bar() {}
Zeigt an:
Warning 1 Arrays as attribute arguments is not CLS-compliant
Für die regelmäßige Verwendung von Reflexionen kann es vorzuziehen sein, mehrere Attribute zu haben, d. H.
[Foo("abc"), Foo("def")]
Dies funktioniert jedoch nicht mit TypeDescriptor/ PropertyDescriptor, wo nur eine einzige Instanz eines Attributs unterstützt wird (entweder der erste oder der letzte Gewinn, ich kann mich nicht erinnern, welcher).
Versuchen Sie, den Konstruktor wie folgt zu deklarieren:
public class MyCustomAttribute : Attribute
{
public MyCustomAttribute(params int[] t)
{
}
}
Dann können Sie es wie folgt verwenden:
[MyCustomAttribute(3, 4, 5)]
Das sollte okay sein. Aus der Spezifikation, Abschnitt 17.2:
Ein Ausdruck E ist ein Attribut-Argument-Ausdruck, wenn alle folgenden Aussagen wahr sind:
Hier ist ein Beispiel:
using System;
[AttributeUsage(AttributeTargets.All, AllowMultiple = false, Inherited = true)]
public class SampleAttribute : Attribute
{
public SampleAttribute(int[] foo)
{
}
}
[Sample(new int[]{1, 3, 5})]
class Test
{
}
Ja, aber Sie müssen das übergebene Array initialisieren. Hier ist ein Beispiel aus einem Zeilentest in unseren Komponententests, bei dem eine variable Anzahl von Befehlszeilenoptionen getestet wird.
[Row( new[] { "-l", "/port:13102", "-lfsw" } )]
public void MyTest( string[] args ) { //... }
Um auf Marc Gravells Antwort zurückzugreifen, können Sie ein Attribut mit Array-Parametern definieren, aber das Anwenden eines Attributs mit einem Array-Parameter ist nicht CLS-kompatibel. Das Definieren eines Attributs mit einer Array-Eigenschaft ist jedoch perfekt CLS-kompatibel.
Mir wurde klar, dass Json.NET, eine CLS-kompatible Bibliothek, eine Attributklasse JsonPropertyAttribute mit einer Eigenschaft namens ItemConverterParameters hat, die ein Array von Objekten ist.