วิธีสร้างแอตทริบิวต์ที่อนุญาตซ้ำกัน


97

ฉันใช้แอตทริบิวต์ที่กำหนดเองซึ่งสืบทอดมาจากคลาสแอตทริบิวต์ ฉันใช้มันแบบนี้:

[MyCustomAttribute("CONTROL")]
[MyCustomAttribute("ALT")]
[MyCustomAttribute("SHIFT")]
[MyCustomAttribute("D")]
public void setColor()
{

}

แต่แสดงข้อผิดพลาด "แอตทริบิวต์" MyCustomAttribute "ที่ซ้ำกัน
ฉันจะสร้างแอตทริบิวต์ที่อนุญาตซ้ำได้อย่างไร

คำตอบ:


186

ติดAttributeUsageแอตทริบิวต์ลงในคลาส Attribute ของคุณ (ใช่นั่นคือคำพูด) และตั้งค่าAllowMultipleเป็นtrue:

[AttributeUsage(AttributeTargets.Method, AllowMultiple = true)]
public sealed class MyCustomAttribute: Attribute

6
แค่อยากรู้ - ทำไมต้องเป็นคลาส "ปิดผนึก"?
Tomas Aschan

18
Microsoft แนะนำให้ปิดผนึกคลาสแอตทริบิวต์ทุกครั้งที่ทำได้: msdn.microsoft.com/en-us/library/2ab31zeh.aspx
Anton Gogolev

3
ทำไมต้องปิดผนึก? กล่าวโดยย่อ: ทำให้การค้นหาแอตทริบิวต์เร็วขึ้นและไม่มีผลกระทบอื่น ๆ
Noel Widmer

ยกเว้นว่าจะหยุดไม่ให้บุคคลอื่นนำรหัสของคุณไปใช้ซ้ำ เป็นที่น่าสังเกตว่าแอตทริบิวต์การตรวจสอบความถูกต้องใน DataAnnotations ไม่ได้ถูกปิดผนึกซึ่งมีประโยชน์อย่างมากเนื่องจากสามารถสร้างความเชี่ยวชาญพิเศษได้
Neutrino

@Neutrino ผนึกควรใช้เมื่อใดก็ตามที่คุณไม่คาดหวังหรือไม่ได้ออกแบบคลาสของคุณให้สืบทอด นอกจากนี้เมื่อการถ่ายทอดทางพันธุกรรมอาจกลายเป็นที่มาของข้อบกพร่องเช่นการใช้งานเธรดที่ปลอดภัย
Francisco Neto

20

AttributeUsageAttribute ;-p

[AttributeUsage(AttributeTargets.Method, AllowMultiple = true)]
public class MyAttribute : Attribute
{}

อย่างไรก็ตามโปรดทราบว่าหากคุณใช้ ComponentModel ( TypeDescriptor) จะสนับสนุนเพียงหนึ่งอินสแตนซ์แอ็ตทริบิวต์ (ต่อประเภทแอ็ตทริบิวต์) ต่อสมาชิก การสะท้อนดิบรองรับจำนวนใด ๆ ...


13

วิธีแก้ของ Antonถูกต้อง แต่ยังมีgotcha อีกตัว

กล่าวโดยย่อเว้นแต่ว่าแอPropertyDescriptor.GetCustomAttributes()ททริบิวต์ที่คุณกำหนดเองจะแทนที่ TypeId การเข้าถึงผ่านจะส่งคืนแอตทริบิวต์ของคุณเพียงอินสแตนซ์เดียว


แต่มันทำงานผ่าน: var customAtt = propertyInfo.GetCustomAttributes <MyCustomAttribute> ();
oo_dev

9

โดยค่าเริ่มต้นAttributes จะถูก จำกัด ให้ใช้กับฟิลด์ / คุณสมบัติ / ฯลฯ เพียงครั้งเดียวเท่านั้น คุณสามารถดูสิ่งนี้ได้จากคำจำกัดความของAttributeคลาสบน MSDN :

[AttributeUsageAttribute(..., AllowMultiple = false)]
public abstract class Attribute : _Attribute

ดังนั้นตามที่คนอื่น ๆ ได้กล่าวไว้คลาสย่อยทั้งหมดจะถูก จำกัด ในลักษณะเดียวกันและหากคุณต้องการหลายอินสแตนซ์ของแอตทริบิวต์เดียวกันคุณต้องตั้งค่าอย่างชัดเจนAllowMultipleเป็นtrue:

[AttributeUsage(..., AllowMultiple = true)]
public class MyCustomAttribute : Attribute

ในแอตทริบิวต์ที่อนุญาตการใช้งานหลายรายการคุณควรแทนที่TypeIdคุณสมบัติเพื่อให้แน่ใจว่าคุณสมบัติเช่นPropertyDescriptor.Attributes ทำงานตามที่คาดไว้ วิธีที่ง่ายที่สุดคือใช้คุณสมบัตินั้นเพื่อส่งคืนอินสแตนซ์แอตทริบิวต์เอง:

[AttributeUsage(..., AllowMultiple = true)]
public class MyCustomAttribute : Attribute
{
    public override object TypeId
    {
        get
        {
            return this;
        }
    }
}

(การโพสต์คำตอบนี้ไม่ใช่เพราะคนอื่นผิด แต่เป็นเพราะคำตอบนี้ครอบคลุม / บัญญัติมากกว่า)


3

อีกทางเลือกหนึ่งให้นึกถึงการออกแบบแอตทริบิวต์ของคุณใหม่เพื่อให้มีลำดับ

[MyCustomAttribute(Sequence="CONTROL,ALT,SHIFT,D")]

หรือ

[MyCustomAttribute("CONTROL-ALT-SHIFT-D")]

จากนั้นแยกวิเคราะห์ค่าเพื่อกำหนดค่าแอตทริบิวต์ของคุณ

สำหรับตัวอย่างของการตรวจสอบนี้ออก AuthorizeAttribute ในรหัสที่มา ASP.NET MVC ที่www.codeplex.com/aspnet


3
เป็นไปได้ที่จะให้คอนMyCustomAttributeสตรัคเตอร์ใช้อาร์เรย์ของสตริง a string[]มีหรือไม่มีโมดิparamsฟายเออร์ จากนั้นสามารถนำไปใช้กับไวยากรณ์[MyCustom("CONTROL", "ALT", "SHIFT", "D")](with params)
Jeppe Stig Nielsen

2

หลังจากคุณเพิ่ม AttributeUsage ตรวจสอบให้แน่ใจว่าคุณได้เพิ่มคุณสมบัตินี้ในคลาส Attribute ของคุณ

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