เป็นไปได้หรือไม่ที่จะสร้างแอตทริบิวต์ที่สามารถเริ่มต้นด้วยจำนวนอาร์กิวเมนต์ได้?
ตัวอย่างเช่น:
[MyCustomAttribute(new int[3,4,5])] // this doesn't work
public MyClass ...
เป็นไปได้หรือไม่ที่จะสร้างแอตทริบิวต์ที่สามารถเริ่มต้นด้วยจำนวนอาร์กิวเมนต์ได้?
ตัวอย่างเช่น:
[MyCustomAttribute(new int[3,4,5])] // this doesn't work
public MyClass ...
คำตอบ:
แอตทริบิวต์จะใช้อาร์เรย์ แม้ว่าคุณจะควบคุมแอตทริบิวต์ แต่คุณยังสามารถใช้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 { }
คุณสามารถทำได้ แต่ไม่สอดคล้องกับ 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
ซึ่งรองรับเพียงอินสแตนซ์เดียวของแอตทริบิวต์ใด ๆ (ไม่ว่าจะชนะครั้งแรกหรือครั้งสุดท้ายฉันจำไม่ได้)
ลองประกาศตัวสร้างดังนี้:
public class MyCustomAttribute : Attribute
{
public MyCustomAttribute(params int[] t)
{
}
}
จากนั้นคุณสามารถใช้งานได้เช่น:
[MyCustomAttribute(3, 4, 5)]
นั่นน่าจะโอเค จากข้อมูลจำเพาะส่วนที่ 17.2:
นิพจน์ E เป็นแอตทริบิวต์ - อาร์กิวเมนต์ - นิพจน์หากข้อความต่อไปนี้ทั้งหมดเป็นจริง:
นี่คือตัวอย่าง:
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
{
}
ใช่ แต่คุณต้องเริ่มต้นอาร์เรย์ที่คุณกำลังส่งผ่านนี่คือตัวอย่างจากการทดสอบแถวในการทดสอบหน่วยของเราที่ทดสอบตัวเลือกบรรทัดคำสั่งจำนวนตัวแปร
[Row( new[] { "-l", "/port:13102", "-lfsw" } )]
public void MyTest( string[] args ) { //... }
คุณสามารถทำได้ อีกตัวอย่างหนึ่งอาจเป็น:
class MyAttribute: Attribute
{
public MyAttribute(params object[] args)
{
}
}
[MyAttribute("hello", 2, 3.14f)]
class Program
{
static void Main(string[] args)
{
}
}
หากต้องการย้อนกลับไปที่คำตอบของ Marc Gravell ใช่คุณสามารถกำหนดแอตทริบิวต์ที่มีพารามิเตอร์อาร์เรย์ได้ แต่การใช้แอตทริบิวต์กับพารามิเตอร์อาร์เรย์นั้นไม่สอดคล้องกับ CLS อย่างไรก็ตามการกำหนดแอตทริบิวต์ด้วยคุณสมบัติอาร์เรย์ก็สอดคล้องกับ CLS อย่างสมบูรณ์แบบ
สิ่งที่ทำให้ฉันรู้ว่า Json.NET ซึ่งเป็นไลบรารีที่เข้ากันได้กับ CLS มีคลาสแอตทริบิวต์ JsonPropertyAttribute ที่มีคุณสมบัติชื่อ ItemConverterParameters ซึ่งเป็นอาร์เรย์ของวัตถุ