C # özniteliğini bir dizi veya başka değişken sayıdaki bağımsız değişkenlerle başlatabilir miyim?


105

Değişken sayıda bağımsız değişkenle başlatılabilen bir öznitelik yaratmak mümkün müdür?

Örneğin:

[MyCustomAttribute(new int[3,4,5])]  // this doesn't work
public MyClass ...

12
Sadece dizi için sözdiziminiz yanlış. "New int [] {3,4,5}" olmalıdır.
David Wengier

Yanıtlar:


179

Nitelikler bir dizi alacaktır. Özniteliği kontrol ediyorsanız, paramsbunun yerine de kullanabilirsiniz (tüketiciler için daha hoş, IMO):

class MyCustomAttribute : Attribute {
    public int[] Values { get; set; }

    public MyCustomAttribute(params int[] values) {
       this.Values = values;
    }
}

[MyCustomAttribute(3, 4, 5)]
class MyClass { }

Dizi oluşturma sözdiziminiz şu anda kapalı:

class MyCustomAttribute : Attribute {
    public int[] Values { get; set; }

    public MyCustomAttribute(int[] values) {
        this.Values = values;
    }
}

[MyCustomAttribute(new int[] { 3, 4, 5 })]
class MyClass { }

33

Yapabilirsiniz, ancak CLS uyumlu değildir:

[assembly: CLSCompliant(true)]

class Foo : Attribute
{
    public Foo(string[] vals) { }
}
[Foo(new string[] {"abc","def"})]
static void Bar() {}

Şovlar:

Warning 1   Arrays as attribute arguments is not CLS-compliant

Düzenli yansıma kullanımı için birden çok özelliğe sahip olmak tercih edilebilir, yani

[Foo("abc"), Foo("def")]

Ancak, bu , herhangi bir özniteliğin yalnızca tek bir örneğinin desteklendiği TypeDescriptor/ ile çalışmaz PropertyDescriptor(ilk veya son kazanır, hangisini hatırlayamıyorum).


3
not: birden çok özellik, özelliğiniz için bir AttributeUsage özniteliği gerektirir. stackoverflow.com/questions/553540/…
russau

23

Yapıcıyı şu şekilde bildirmeyi deneyin:

public class MyCustomAttribute : Attribute
{
    public MyCustomAttribute(params int[] t)
    {
    }
}

O zaman bunu şu şekilde kullanabilirsiniz:

[MyCustomAttribute(3, 4, 5)]


12

Bu tamam olmalı. Spesifikasyondan bölüm 17.2:

Aşağıdaki ifadelerin tümü doğruysa , E ifadesi bir öznitelik-bağımsız değişken-ifadesidir :

  • E tipi bir öznitelik parametresi türüdür (§17.1.3).
  • Derleme zamanında, E'nin değeri aşağıdakilerden birine çözümlenebilir:
    • Sabit bir değer.
    • Bir System.Type nesnesi.
    • Öznitelik bağımsız değişken ifadelerinin tek boyutlu dizisi .

İşte bir örnek:

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

5
CLS uyumluluğuna dikkat edin
Marc Gravell

5

Evet, ancak geçmekte olduğunuz diziyi başlatmanız gerekiyor. Burada, değişken sayıda komut satırı seçeneklerini test eden birim testlerimizde bir satır testinden bir örnek var;

[Row( new[] { "-l", "/port:13102", "-lfsw" } )]
public void MyTest( string[] args ) { //... }

2

Bunu yapabilirsin. Başka bir örnek şunlar olabilir:

class MyAttribute: Attribute
{
    public MyAttribute(params object[] args)
    {
    }
}

[MyAttribute("hello", 2, 3.14f)]
class Program
{
    static void Main(string[] args)
    {
    }
}

1

Marc Gravell'in cevabına geri dönmek için, evet, dizi parametreleriyle bir öznitelik tanımlayabilirsiniz, ancak bir dizi parametresiyle bir öznitelik uygulamak CLS uyumlu değildir. Bununla birlikte, bir dizi özelliğine sahip bir özniteliği tanımlamak tamamen CLS uyumludur.

Bunu fark etmemi sağlayan şey, CLS uyumlu bir kitaplık olan Json.NET'in, bir nesne dizisi olan ItemConverterParameters adlı bir özelliğe sahip bir JsonPropertyAttribute öznitelik sınıfına sahip olmasıdır.

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.