ฉันสามารถเริ่มต้นแอตทริบิวต์ C # ด้วยอาร์เรย์หรือจำนวนอาร์กิวเมนต์อื่น ๆ ได้หรือไม่


105

เป็นไปได้หรือไม่ที่จะสร้างแอตทริบิวต์ที่สามารถเริ่มต้นด้วยจำนวนอาร์กิวเมนต์ได้?

ตัวอย่างเช่น:

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

12
คุณมีไวยากรณ์ของคุณสำหรับอาร์เรย์ผิด ควรเป็น "new int [] {3,4,5}"
David Wengier

คำตอบ:


179

แอตทริบิวต์จะใช้อาร์เรย์ แม้ว่าคุณจะควบคุมแอตทริบิวต์ แต่คุณยังสามารถใช้paramsแทนได้ (ซึ่งดีกว่าสำหรับผู้บริโภค IMO):

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

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

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

ไวยากรณ์สำหรับการสร้างอาร์เรย์ของคุณจะปิด:

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

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

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

33

คุณสามารถทำได้ แต่ไม่สอดคล้องกับ CLS:

[assembly: CLSCompliant(true)]

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

การแสดง:

Warning 1   Arrays as attribute arguments is not CLS-compliant

สำหรับการใช้งานการสะท้อนแสงเป็นประจำอาจดีกว่าที่จะมีหลายแอตทริบิวต์เช่น

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

อย่างไรก็ตามสิ่งนี้ใช้ไม่ได้กับTypeDescriptor/ PropertyDescriptorซึ่งรองรับเพียงอินสแตนซ์เดียวของแอตทริบิวต์ใด ๆ (ไม่ว่าจะชนะครั้งแรกหรือครั้งสุดท้ายฉันจำไม่ได้)


3
หมายเหตุ: แอตทริบิวต์หลายรายการต้องการแอตทริบิวต์ AttributeUsage ในแอตทริบิวต์ของคุณ stackoverflow.com/questions/553540/…
russau

23

ลองประกาศตัวสร้างดังนี้:

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

จากนั้นคุณสามารถใช้งานได้เช่น:

[MyCustomAttribute(3, 4, 5)]


12

นั่นน่าจะโอเค จากข้อมูลจำเพาะส่วนที่ 17.2:

นิพจน์ E เป็นแอตทริบิวต์ - อาร์กิวเมนต์ - นิพจน์หากข้อความต่อไปนี้ทั้งหมดเป็นจริง:

  • ประเภทของ E คือประเภทพารามิเตอร์แอตทริบิวต์ (§17.1.3)
  • ในเวลาคอมไพล์ค่าของ E สามารถแก้ไขได้ดังต่อไปนี้:
    • ค่าคงที่
    • วัตถุ System.Type
    • อาร์เรย์หนึ่งมิติของแอตทริบิวต์อาร์กิวเมนต์แสดงออก

นี่คือตัวอย่าง:

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
Marc Gravell

5

ใช่ แต่คุณต้องเริ่มต้นอาร์เรย์ที่คุณกำลังส่งผ่านนี่คือตัวอย่างจากการทดสอบแถวในการทดสอบหน่วยของเราที่ทดสอบตัวเลือกบรรทัดคำสั่งจำนวนตัวแปร

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

2

คุณสามารถทำได้ อีกตัวอย่างหนึ่งอาจเป็น:

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

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

1

หากต้องการย้อนกลับไปที่คำตอบของ Marc Gravell ใช่คุณสามารถกำหนดแอตทริบิวต์ที่มีพารามิเตอร์อาร์เรย์ได้ แต่การใช้แอตทริบิวต์กับพารามิเตอร์อาร์เรย์นั้นไม่สอดคล้องกับ CLS อย่างไรก็ตามการกำหนดแอตทริบิวต์ด้วยคุณสมบัติอาร์เรย์ก็สอดคล้องกับ CLS อย่างสมบูรณ์แบบ

สิ่งที่ทำให้ฉันรู้ว่า Json.NET ซึ่งเป็นไลบรารีที่เข้ากันได้กับ CLS มีคลาสแอตทริบิวต์ JsonPropertyAttribute ที่มีคุณสมบัติชื่อ ItemConverterParameters ซึ่งเป็นอาร์เรย์ของวัตถุ

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.