คุณลักษณะใน. NET คืออะไร?


คำตอบ:


146

เมตาดาต้า ข้อมูลเกี่ยวกับวัตถุ / วิธีการ / คุณสมบัติของคุณ

ตัวอย่างเช่นฉันอาจประกาศแอตทริบิวต์ที่เรียกว่า: DisplayOrder เพื่อให้ฉันสามารถควบคุมได้อย่างง่ายดายว่าคุณสมบัติการสั่งซื้อใดควรปรากฏใน UI จากนั้นฉันสามารถต่อท้ายคลาสและเขียนส่วนประกอบ GUI บางอย่างที่แยกคุณลักษณะและสั่งซื้อองค์ประกอบ UI อย่างเหมาะสม

public class DisplayWrapper
{
    private UnderlyingClass underlyingObject;

    public DisplayWrapper(UnderlyingClass u)
    {
        underlyingObject = u;
    }

    [DisplayOrder(1)]
    public int SomeInt
    {
        get
        {
            return underlyingObject .SomeInt;
        }
    }

    [DisplayOrder(2)]
    public DateTime SomeDate
    {
        get
        {
            return underlyingObject .SomeDate;
        }
    }
}

ดังนั้นจึงมั่นใจได้ว่า SomeInt จะแสดงเสมอก่อน SomeDate เมื่อทำงานกับองค์ประกอบ GUI ที่กำหนดเองของฉัน

อย่างไรก็ตามคุณจะเห็นพวกเขาใช้บ่อยที่สุดนอกสภาพแวดล้อมการเข้ารหัสโดยตรง ตัวอย่างเช่น Windows Designer ใช้มันอย่างกว้างขวางดังนั้นจึงรู้วิธีจัดการกับวัตถุที่ทำเอง ใช้ BrowsableAttribute ดังนี้:

[Browsable(false)]
public SomeCustomType DontShowThisInTheDesigner
{
    get{/*do something*/}
}

บอกให้ผู้ออกแบบไม่แสดงรายการนี้ในคุณสมบัติที่มีอยู่ในหน้าต่างคุณสมบัติขณะออกแบบตัวอย่างเช่น

คุณยังสามารถใช้พวกเขาสำหรับการสร้างโค้ดการดำเนินการก่อนการคอมไพล์ (เช่น Post-Sharp) หรือการดำเนินการแบบรันไทม์เช่น Reflection.Emit ตัวอย่างเช่นคุณสามารถเขียนรหัสเล็กน้อยสำหรับการทำโปรไฟล์ที่หุ้มด้วยการโทรทุกครั้งที่รหัสของคุณทำและเวลา คุณสามารถ "ยกเลิก" เวลาด้วยแอตทริบิวต์ที่คุณวางไว้บนวิธีการเฉพาะ

public void SomeProfilingMethod(MethodInfo targetMethod, object target, params object[] args)
{
    bool time = true;
    foreach (Attribute a in target.GetCustomAttributes())
    {
        if (a.GetType() is NoTimingAttribute)
        {
            time = false;
            break;
        }
    }
    if (time)
    {
        StopWatch stopWatch = new StopWatch();
        stopWatch.Start();
        targetMethod.Invoke(target, args);
        stopWatch.Stop();
        HandleTimingOutput(targetMethod, stopWatch.Duration);
    }
    else
    {
        targetMethod.Invoke(target, args);
    }
}

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

public class DisplayOrderAttribute : Attribute
{
    private int order;

    public DisplayOrderAttribute(int order)
    {
        this.order = order;
    }

    public int Order
    {
        get { return order; }
    }
}

และจำไว้ว่าเมื่อคุณใช้แอททริบิวต์คุณสามารถละเว้นคำต่อท้าย "แอททริบิว" คอมไพเลอร์จะเพิ่มสิ่งนั้นให้คุณ

หมายเหตุ:คุณสมบัติไม่ได้ทำอะไรด้วยตัวเอง - ต้องมีรหัสอื่นที่ใช้พวกเขา บางครั้งรหัสนั้นถูกเขียนขึ้นสำหรับคุณ แต่บางครั้งคุณต้องเขียนด้วยตัวเอง ตัวอย่างเช่นคอมไพเลอร์ C # ใส่ใจบางเฟรมเวิร์กเฟรมเวิร์กใช้บางอย่าง (เช่น NUnit ค้นหา [TestFixture] ในคลาสและ [Test] ในวิธีการทดสอบเมื่อโหลดชุดประกอบ)
ดังนั้นเมื่อสร้างแอตทริบิวต์ที่กำหนดเองของคุณเองโปรดทราบว่ามันจะไม่ส่งผลกระทบต่อพฤติกรรมของรหัสของคุณเลย คุณจะต้องเขียนส่วนอื่น ๆ ที่ตรวจสอบคุณสมบัติ (ผ่านการสะท้อน) และดำเนินการกับพวกเขา


32
สำหรับสิ่งที่คุ้มค่านี่คือรายการคุณลักษณะ. NET ทั้งหมด (ในตัว): msdn.microsoft.com/en-us/library/aa311259(VS.71).aspx
wprl

1
คุณจะใช้ "SomeProfilingMethod" เป็นแอตทริบิวต์ได้อย่างไร
RayLoveless

@RayLoveless ไม่ใช่แอ็ตทริบิวต์ SomeProfilingMethod เป็นโค้ดเครื่องมือที่กำลังมองหาแอ็ตทริบิวต์การทำโปรไฟล์ ในตัวอย่างที่ฉันให้มองหาแอตทริบิวต์ "การไม่เข้าร่วม" (NoTimingAttribute) ซึ่งตรงข้ามกับ "การเลือกเข้า" แนวคิดก็คือมันคูณทุกอย่าง
Quibblesome

@Quibblesome คุณสามารถเพิ่มบางอย่างเช่น "แอตทริบิวต์ไม่ได้ทำอะไรด้วยตัวเอง - ต้องมีรหัสอื่น ๆ ที่จะใช้ (คอมไพเลอร์ใส่ใจเกี่ยวกับคู่กรอบที่แตกต่างกันใช้บางส่วน) เพียงแค่การสร้างแอตทริบิวต์จะไม่ส่งผลกระทบต่อพฤติกรรมของรหัส - คุณต้องเขียนส่วนอื่น ๆ ที่ตรวจสอบคุณสมบัติ (ผ่านการสะท้อน) และดำเนินการกับพวกเขา " (หรือฉันสามารถทำได้ถ้าคุณโอเค) หลายคนคาดหวังว่าคุณลักษณะต่างๆจะทำงานได้อย่างมหัศจรรย์และไม่มีคำตอบใด ๆ (หรือเพียงแค่ลิงก์ไปยังstackoverflow.com/questions/4879521/ซึ่งครอบคลุมเนื้อหานี้)
Alexei Levenkov

เฉพาะในกรณีที่คุณหยุดใช้ Bing Nah j / k ฉันใช้ DuckDuckGo เป็นหลักซึ่งใช้ Bing iirc เป็นหลัก :)
Quibblesome

36

หลายคนตอบแล้ว แต่ยังไม่มีใครพูดถึงเรื่องนี้ ...

คุณสมบัติที่ใช้อย่างหนักกับการสะท้อน การสะท้อนค่อนข้างช้าอยู่แล้ว

การทำเครื่องหมายแอตทริบิวต์ที่กำหนดเองของคุณเป็นสิ่งที่คุ้มค่ามากsealedคลาสเพื่อเพิ่มประสิทธิภาพการทำงานของรันไทม์

นอกจากนี้ยังเป็นความคิดที่ดีที่จะต้องพิจารณาที่มันจะเหมาะสมที่จะใช้สถานที่ดังกล่าวแอตทริบิวต์และแอตทริบิวต์แอตทริบิวต์ของคุณ (!) AttributeUsageเพื่อบ่งชี้นี้ผ่านทาง รายการประเพณีการใช้คุณลักษณะที่มีอยู่อาจทำให้คุณประหลาดใจ:

  • การชุมนุม
  • โมดูล
  • ชั้น
  • โครงสร้าง
  • enum
  • นวกรรมิก
  • วิธี
  • คุณสมบัติ
  • สนาม
  • เหตุการณ์
  • อินเตอร์เฟซ
  • พารามิเตอร์
  • ตัวแทน
  • returnValue
  • GenericParameter
  • ทั้งหมด

นอกจากนี้ยังยอดเยี่ยมที่แอตทริบิวต์ AttributeUsage เป็นส่วนหนึ่งของลายเซ็นของแอตทริบิวต์ AttributeUsage โอ้โหสำหรับการพึ่งพาแบบวงกลม!

[AttributeUsageAttribute(AttributeTargets.Class, Inherited = true)]
public sealed class AttributeUsageAttribute : Attribute

13

แอตทริบิวต์เป็นข้อมูลประเภทเมตาสำหรับการแท็กคลาส ซึ่งมักใช้ใน WinForms เพื่อซ่อนตัวควบคุมจากแถบเครื่องมือ แต่สามารถนำไปใช้ในแอปพลิเคชันของคุณเองเพื่อเปิดใช้งานอินสแตนซ์ของคลาสที่แตกต่างกันเพื่อให้ทำงานในวิธีเฉพาะ

เริ่มต้นด้วยการสร้างแอตทริบิวต์:

[AttributeUsage(AttributeTargets.Class, AllowMultiple=false, Inherited=true)]
public class SortOrderAttribute : Attribute
{
    public int SortOrder { get; set; }

    public SortOrderAttribute(int sortOrder)
    {
        this.SortOrder = sortOrder;
    }
}

คลาสแอ็ตทริบิวต์ทั้งหมดต้องมีส่วนต่อท้าย "Attribute" ที่ถูกต้อง
หลังจากเสร็จสิ้นการสร้างคลาสที่ใช้คุณลักษณะ

[SortOrder(23)]
public class MyClass
{
    public MyClass()
    {
    }
}

ตอนนี้คุณสามารถตรวจสอบคลาสเฉพาะ ' SortOrderAttribute(ถ้ามี) โดยทำดังต่อไปนี้:

public class MyInvestigatorClass
{
    public void InvestigateTheAttribute()
    {
        // Get the type object for the class that is using
        // the attribute.
        Type type = typeof(MyClass);

        // Get all custom attributes for the type.
        object[] attributes = type.GetCustomAttributes(
            typeof(SortOrderAttribute), true);

        // Now let's make sure that we got at least one attribute.
        if (attributes != null && attributes.Length > 0)
        {
            // Get the first attribute in the list of custom attributes
            // that is of the type "SortOrderAttribute". This should only
            // be one since we said "AllowMultiple=false".
            SortOrderAttribute attribute = 
                attributes[0] as SortOrderAttribute;

            // Now we can get the sort order for the class "MyClass".
            int sortOrder = attribute.SortOrder;
        }
    }
}

หากคุณต้องการอ่านเพิ่มเติมเกี่ยวกับเรื่องนี้คุณสามารถดูMSDNซึ่งมีคำอธิบายที่ดีอยู่เสมอ
ฉันหวังว่านี่จะช่วยคุณได้!


5

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

สำหรับสิ่งที่พวกเขาดีสำหรับ ... มีการใช้งานเกือบไร้ขีด จำกัด สำหรับพวกเขา

http://www.codeproject.com/KB/cs/dotnetattributes.aspx


1
"ฟังก์ชั่น" เป็นคำที่ผิดที่นี่; เป็นข้อมูลเมตาไม่ใช่ฟังก์ชัน
Marc Gravell

5

แอตทริบิวต์เหมือนเมทาดาทาที่ใช้กับคลาสวิธีการหรือชุดประกอบ

สิ่งเหล่านี้ดีสำหรับทุกสิ่ง (การสร้างภาพดีบั๊กเกอร์ทำเครื่องหมายสิ่งที่ล้าสมัยทำเครื่องหมายสิ่งต่าง ๆ ว่าเป็นอนุกรมได้รายการไม่มีที่สิ้นสุด)

การสร้างแบบกำหนดเองของคุณเองนั้นง่ายเหมือนพาย เริ่มที่นี่:

http://msdn.microsoft.com/en-us/library/sw480ze8(VS.71).aspx


5

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

[AttributeUsage (AttributeTargets::Class)]
public ref class ControlDescriptionAttribute : Attribute
{
public:
  ControlDescriptionAttribute (String ^name, String ^description) :
    _name (name),
    _description (description)
  {
  }

  property String ^Name
  {
    String ^get () { return _name; }
  }

  property String ^Description
  {
    String ^get () { return _description; }
  }

private:
  String
    ^ _name,
    ^ _description;
};

และฉันนำไปใช้กับชั้นเรียนเช่นนี้:

[ControlDescription ("Pie Chart", "Displays a pie chart")]
public ref class PieControl sealed : UserControl
{
  // stuff
};

ซึ่งเป็นสิ่งที่ผู้โพสต์ก่อนหน้าได้พูด

ในการใช้แอททริบิวตัวแก้ไขมีGeneric::List <Type>ประเภทการควบคุมที่มี มีกล่องรายการที่ผู้ใช้สามารถลากจากและวางลงบนเพจเพื่อสร้างอินสแตนซ์ของตัวควบคุมได้ เพื่อเติมกล่องรายการฉันได้รับControlDescriptionAttributeการควบคุมและกรอกรายการในรายการ:

// done for each control type
array <Object ^>
  // get all the custom attributes
  ^attributes = controltype->GetCustomAttributes (true);

Type
  // this is the one we're interested in
  ^attributetype = ECMMainPageDisplay::ControlDescriptionAttribute::typeid;

// iterate over the custom attributes
for each (Object ^attribute in attributes)
{
  if (attributetype->IsInstanceOfType (attribute))
  {
    ECMMainPageDisplay::ControlDescriptionAttribute
      ^description = safe_cast <ECMMainPageDisplay::ControlDescriptionAttribute ^> (attribute);

    // get the name and description and create an entry in the list
    ListViewItem
      ^item = gcnew ListViewItem (description->Name);

    item->Tag = controltype->Name;
    item->SubItems->Add (description->Description);

    mcontrols->Items->Add (item);
    break;
  }
}

หมายเหตุ: ข้างต้นคือ C ++ / CLI แต่ไม่ยากที่จะแปลงเป็น C # (ใช่ฉันรู้ C ++ / CLI เป็นสิ่งที่น่ารังเกียจ แต่มันคือสิ่งที่ฉันต้องทำงานกับ :-()

คุณสามารถใส่คุณลักษณะต่าง ๆ ลงไปได้และมีคุณสมบัติที่กำหนดไว้ล่วงหน้ามากมาย ตัวแก้ไขที่กล่าวถึงด้านบนยังค้นหาแอตทริบิวต์ที่กำหนดเองบนคุณสมบัติที่อธิบายคุณสมบัติและวิธีแก้ไข

เมื่อคุณได้รับความคิดทั้งหมดคุณจะสงสัยว่าคุณเคยอยู่โดยปราศจากพวกเขา


4

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

การใช้คุณลักษณะและการรู้ถึงสถานการณ์ที่เหมาะสมสำหรับการใช้งานของพวกเขาคืองานจำนวนมาก


3

แอ็ตทริบิวต์คือบิตของข้อมูลที่คุณต้องการแนบกับประเภทของคุณ(คลาส, วิธีการ, เหตุการณ์, enums ฯลฯ )

แนวคิดก็คือในขณะใช้งานบางประเภท / กรอบ / เครื่องมืออื่น ๆ จะสอบถามของคุณชนิดสำหรับข้อมูลในคุณลักษณะและดำเนินการตามนั้น

ตัวอย่างเช่น Visual Studio สามารถสอบถามคุณลักษณะในตัวควบคุมบุคคลที่สามเพื่อหาว่าคุณสมบัติของตัวควบคุมใดควรปรากฏในบานหน้าต่างคุณสมบัติในขณะออกแบบ

แอ็ตทริบิวต์ยังสามารถใช้ใน Aspect Oriented Programming เพื่อฉีด / จัดการกับวัตถุที่รันไทม์ตามคุณลักษณะที่ตกแต่งและเพิ่มการตรวจสอบการบันทึก ฯลฯ ไปยังวัตถุโดยไม่ส่งผลกระทบต่อตรรกะทางธุรกิจของวัตถุ


2

คุณสามารถใช้แอตทริบิวต์ที่กำหนดเองเป็นวิธีง่ายๆในการกำหนดค่าแท็กในคลาสย่อยโดยไม่ต้องเขียนรหัสเดียวกันซ้ำแล้วซ้ำอีกสำหรับแต่ละคลาสย่อย ฉันเจอตัวอย่างที่กระชับโดย John Watersเกี่ยวกับวิธีกำหนดและใช้แอตทริบิวต์ที่กำหนดเองในรหัสของคุณเอง

มีบทช่วยสอนที่http://msdn.microsoft.com/en-us/library/aa288454(VS.71).aspx


2

หากต้องการเริ่มต้นสร้างแอตทริบิวต์ให้เปิดไฟล์ต้นฉบับ C # จากนั้นพิมพ์attributeและกด [TAB] มันจะขยายไปยังเทมเพลตสำหรับแอตทริบิวต์ใหม่


6
มันตอบคำถามได้อย่างไร ควรเป็นความเห็นไม่ใช่คำตอบ
gdoron ให้การสนับสนุน Monica

1

คุณสมบัติทั่วไปยังใช้สำหรับการเขียนโปรแกรมเชิงมุมมอง สำหรับตัวอย่างของการตรวจสอบโครงการPostSharp

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