คุณลักษณะใดใน. NET สิ่งที่ดีสำหรับสิ่งนั้นและฉันจะสร้างคุณลักษณะของตัวเองได้อย่างไร
คุณลักษณะใดใน. NET สิ่งที่ดีสำหรับสิ่งนั้นและฉันจะสร้างคุณลักษณะของตัวเองได้อย่างไร
คำตอบ:
เมตาดาต้า ข้อมูลเกี่ยวกับวัตถุ / วิธีการ / คุณสมบัติของคุณ
ตัวอย่างเช่นฉันอาจประกาศแอตทริบิวต์ที่เรียกว่า: 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] ในวิธีการทดสอบเมื่อโหลดชุดประกอบ)
ดังนั้นเมื่อสร้างแอตทริบิวต์ที่กำหนดเองของคุณเองโปรดทราบว่ามันจะไม่ส่งผลกระทบต่อพฤติกรรมของรหัสของคุณเลย คุณจะต้องเขียนส่วนอื่น ๆ ที่ตรวจสอบคุณสมบัติ (ผ่านการสะท้อน) และดำเนินการกับพวกเขา
หลายคนตอบแล้ว แต่ยังไม่มีใครพูดถึงเรื่องนี้ ...
คุณสมบัติที่ใช้อย่างหนักกับการสะท้อน การสะท้อนค่อนข้างช้าอยู่แล้ว
การทำเครื่องหมายแอตทริบิวต์ที่กำหนดเองของคุณเป็นสิ่งที่คุ้มค่ามากsealed
คลาสเพื่อเพิ่มประสิทธิภาพการทำงานของรันไทม์
นอกจากนี้ยังเป็นความคิดที่ดีที่จะต้องพิจารณาที่มันจะเหมาะสมที่จะใช้สถานที่ดังกล่าวแอตทริบิวต์และแอตทริบิวต์แอตทริบิวต์ของคุณ (!) AttributeUsage
เพื่อบ่งชี้นี้ผ่านทาง รายการประเพณีการใช้คุณลักษณะที่มีอยู่อาจทำให้คุณประหลาดใจ:
นอกจากนี้ยังยอดเยี่ยมที่แอตทริบิวต์ AttributeUsage เป็นส่วนหนึ่งของลายเซ็นของแอตทริบิวต์ AttributeUsage โอ้โหสำหรับการพึ่งพาแบบวงกลม!
[AttributeUsageAttribute(AttributeTargets.Class, Inherited = true)]
public sealed class AttributeUsageAttribute : Attribute
แอตทริบิวต์เป็นข้อมูลประเภทเมตาสำหรับการแท็กคลาส ซึ่งมักใช้ใน 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ซึ่งมีคำอธิบายที่ดีอยู่เสมอ
ฉันหวังว่านี่จะช่วยคุณได้!
แอตทริบิวต์เป็นคลาสที่มีฟังก์ชั่นบางอย่างที่คุณสามารถนำไปใช้กับวัตถุในรหัสของคุณ เมื่อต้องการสร้างให้สร้างคลาสที่สืบทอดจาก System.Attribute
สำหรับสิ่งที่พวกเขาดีสำหรับ ... มีการใช้งานเกือบไร้ขีด จำกัด สำหรับพวกเขา
แอตทริบิวต์เหมือนเมทาดาทาที่ใช้กับคลาสวิธีการหรือชุดประกอบ
สิ่งเหล่านี้ดีสำหรับทุกสิ่ง (การสร้างภาพดีบั๊กเกอร์ทำเครื่องหมายสิ่งที่ล้าสมัยทำเครื่องหมายสิ่งต่าง ๆ ว่าเป็นอนุกรมได้รายการไม่มีที่สิ้นสุด)
การสร้างแบบกำหนดเองของคุณเองนั้นง่ายเหมือนพาย เริ่มที่นี่:
http://msdn.microsoft.com/en-us/library/sw480ze8(VS.71).aspx
ในโครงการที่ฉันกำลังทำงานอยู่มีชุดของวัตถุ 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 เป็นสิ่งที่น่ารังเกียจ แต่มันคือสิ่งที่ฉันต้องทำงานกับ :-()
คุณสามารถใส่คุณลักษณะต่าง ๆ ลงไปได้และมีคุณสมบัติที่กำหนดไว้ล่วงหน้ามากมาย ตัวแก้ไขที่กล่าวถึงด้านบนยังค้นหาแอตทริบิวต์ที่กำหนดเองบนคุณสมบัติที่อธิบายคุณสมบัติและวิธีแก้ไข
เมื่อคุณได้รับความคิดทั้งหมดคุณจะสงสัยว่าคุณเคยอยู่โดยปราศจากพวกเขา
ดังที่กล่าวไว้แอตทริบิวต์มีความง่ายในการสร้าง อีกส่วนหนึ่งของงานคือการสร้างรหัสที่ใช้งาน ในกรณีส่วนใหญ่คุณจะใช้การสะท้อนที่รันไทม์เพื่อเปลี่ยนพฤติกรรมตามการมีอยู่ของคุณสมบัติหรือคุณสมบัติของมัน นอกจากนี้ยังมีสถานการณ์จำลองที่คุณจะตรวจสอบคุณลักษณะของรหัสที่รวบรวมเพื่อทำการวิเคราะห์แบบคงที่ ตัวอย่างเช่นพารามิเตอร์อาจถูกทำเครื่องหมายเป็นไม่เป็นโมฆะและเครื่องมือวิเคราะห์สามารถใช้สิ่งนี้เป็นคำใบ้
การใช้คุณลักษณะและการรู้ถึงสถานการณ์ที่เหมาะสมสำหรับการใช้งานของพวกเขาคืองานจำนวนมาก
แอ็ตทริบิวต์คือบิตของข้อมูลที่คุณต้องการแนบกับประเภทของคุณ(คลาส, วิธีการ, เหตุการณ์, enums ฯลฯ )
แนวคิดก็คือในขณะใช้งานบางประเภท / กรอบ / เครื่องมืออื่น ๆ จะสอบถามของคุณชนิดสำหรับข้อมูลในคุณลักษณะและดำเนินการตามนั้น
ตัวอย่างเช่น Visual Studio สามารถสอบถามคุณลักษณะในตัวควบคุมบุคคลที่สามเพื่อหาว่าคุณสมบัติของตัวควบคุมใดควรปรากฏในบานหน้าต่างคุณสมบัติในขณะออกแบบ
แอ็ตทริบิวต์ยังสามารถใช้ใน Aspect Oriented Programming เพื่อฉีด / จัดการกับวัตถุที่รันไทม์ตามคุณลักษณะที่ตกแต่งและเพิ่มการตรวจสอบการบันทึก ฯลฯ ไปยังวัตถุโดยไม่ส่งผลกระทบต่อตรรกะทางธุรกิจของวัตถุ
คุณสามารถใช้แอตทริบิวต์ที่กำหนดเองเป็นวิธีง่ายๆในการกำหนดค่าแท็กในคลาสย่อยโดยไม่ต้องเขียนรหัสเดียวกันซ้ำแล้วซ้ำอีกสำหรับแต่ละคลาสย่อย ฉันเจอตัวอย่างที่กระชับโดย John Watersเกี่ยวกับวิธีกำหนดและใช้แอตทริบิวต์ที่กำหนดเองในรหัสของคุณเอง
มีบทช่วยสอนที่http://msdn.microsoft.com/en-us/library/aa288454(VS.71).aspx
หากต้องการเริ่มต้นสร้างแอตทริบิวต์ให้เปิดไฟล์ต้นฉบับ C # จากนั้นพิมพ์attribute
และกด [TAB] มันจะขยายไปยังเทมเพลตสำหรับแอตทริบิวต์ใหม่
คุณสมบัติทั่วไปยังใช้สำหรับการเขียนโปรแกรมเชิงมุมมอง สำหรับตัวอย่างของการตรวจสอบโครงการPostSharp