مشخصات مقاله
-
1619
-
0.0
-
6952
-
0
-
0
آموزش Attribute در C#
صفتها
صفتها برچسبهایی اعلانی هستند که در انتقال اطلاعات مربوط به رفتارهای عناصر مختلف مانند کلاسها، متدها، ساختارها، شمارندهها، اسمبلیها و ... به زمان اجرا، نقش دارند. شما میتوانید با استفاده از این صفتها اطلاعات اعلانی را به یک برنامه اضافه کنید. این برچسبها با براکت ([]) نمایش داده میشوند و بالای عنصری که قرار است استفاده شود قرار میگیرند.
صفتها در اضافه کردن متادیتاهایی مانند دستورالعمل کامپایلر و اطلاعات دیگر مانند کامنت ها، توصیفها، متدها و کلاسها کاربرد دارند. در فریمورک.Net دو نوع صفت وجود دارد: صفات از پیش تعریف شده و صفات با ساخت اختصاصی.
مشخص کردن صفت
سینتکس مشخص کردن صفات را میتوانید در زیر مشاهده کنید:
[attribute(positional_parameters, name_parameter = value, ...)] element
اسم و مقدار صفت داخل براکت، قبل از عنصری که این صفت در آن به کار گرفته شده است مشخص میشوند. پارامترهای مرتبهای اطلاعات اساسی و اسم پارامترها اطلاعات اختیاری را مشخص میکنند.
صفات از پیش تعریف شده
فریمورک.Net سه صفت از پیش تعریف شدهی زیر را فراهم میکند:
- AttributeUsage
- شرطی
- منسوخ
AttributeUsage
صفت از پیش تعریف شدهی AttributeUsage چگونگی استفاده از یک کلاس صفت اختصاصی را بیان میکند. این صفت نوع آیتمهایی که میتواند در آنها اعمال شود را مشخص میکند.
سینتکس مشخص کردن این صفت را میتوانید در زیر مشاهده کنید:
[AttributeUsage ( validon, AllowMultiple = allowmultiple, Inherited = inherited )]
که در آن،
- پارامتر validon عناصری زبانی را مشخص میکند که این صفت میتواند در آنها قرار بگیرد. این پارامتر ترکیبی از مقدار شمارندهی AttributeTargets است. مقدار پیشفرض برابر با AttributeTargets.All است.
- پارامتر allowmultiple (اختیاری) مقدار ویژگی AllowMultiple این صفت که یک مقدار بولی است را فراهم میکند. اگر این مقدار true باشد، این صفت چند کاربری خواهد بود. مقدار پیشفرض false (تک کاربری) است.
- پارامتر inherited (اختیاری) مقدار ویژگی Inherited این صفت که یک مقدار بولی است را مشخص میکند. اگر این مقدار true باشد، این صفت توسط کلاسهای به دست آمده به ارث میرسد. مقدار پیشفرض برابر با false (به ارث نرسیده) است.
برای مثال:
[AttributeUsage( AttributeTargets.Class | AttributeTargets.Constructor | AttributeTargets.Field | AttributeTargets.Method | AttributeTargets.Property, AllowMultiple = true)]
شرطی
این صفت از پیش تعریف شده یک متد را نشان میکند که اجرا شدن این متد به یک شناسهی پیشپردازشی مشخص بستگی دارد.
این صفت باعث میشود کامپایل شرطی فراخوانهای متد با توجه به مقدار مشخص شده مانند Debug یا Trace انجام شود. برای مثال این صفت در زمان رفع اشکال یک کد، مقادیر متغیرها را نمایش میدهد.
سینتکس مشخص کردن این صفت را میتوانید در زیر مشاهده کنید:
[Conditional( conditionalSymbol )]
برای مثال
[Conditional("DEBUG")]
در مثال زیر این صفت نمایش داده شده است:
#define DEBUG
using System;
using System.Diagnostics;
public class Myclass {
[Conditional("DEBUG")]
public static void Message(string msg) {
Console.WriteLine(msg);
}
}
class Test {
static void function1() {
Myclass.Message("In Function 1.");
function2();
}
static void function2() {
Myclass.Message("In Function 2.");
}
public static void Main() {
Myclass.Message("In Main function.");
function1();
Console.ReadKey();
}
}
زمانی که کد بالا کامپایل و اجرا میشود، نتیجهی زیر داده میشود:
In Main function In Function 1 In Function 2
منسوخ
این صفت از پیش تعریف شده یکی از نهادهای برنامه را نشان میکند که دیگر نباید از آن استفاده کرد. شما با کمک این صفت میتوانید به کامپایلر بگویید که یکی از عناصر هدف مشخص را دور بیاندازد. مثلاً زمانی که در کلاسی در حال استفاده از متد جدیدی هستید و همچنان میخواهید متد قدیمی را در کلاس حفظ کنید، میتوانید با نمایش دادن پیامی تحت عنوان متد جدید باید به جای متد قدیمی استفاده شود، این متد را منسوخ کنید.
سینتکس مشخص کردن این صفت در زیر نشان داده شده است:
[Obsolete ( message )] [Obsolete ( message, iserror )]
که در آن،
- پارامتر message رشتهای است که دلیل منسوخ بودن آیتم و جایگزین مورد استفادهی آن را توصیف میکند.
- پارامتر iserror یک مقدار بولی است. اگر این مقدار true باشد، در این صورت کامپایلر استفاده از این آیتم را برابر با خطا در نظر میگیرد. مقدار پیشفرض false است (کامپایلر هشدار میدهد).
در برنامهی زیر این صفت نمایش داده شده است:
using System;
public class MyClass {
[Obsolete("Don't use OldMethod, use NewMethod instead", true)]
static void OldMethod() {
Console.WriteLine("It is the old method");
}
static void NewMethod() {
Console.WriteLine("It is the new method");
}
public static void Main() {
OldMethod();
}
}
زمانی که بخواهید این برنامه را کامپایل کنید، کامپایلر پیام خطای زیر را نمایش میدهد:
Don't use OldMethod, use NewMethod instead
ایجاد صفات اختصاصی
فریمورک.Net این امکان را فراهم میکند تا بتوان صفاتی اختصاصی را ایجاد کرد که بتوان از آنها جهت ذخیرهسازی اطلاعات اعلانی استفاده کرد و آنها را در زمان اجرا بازیابی نمود. این اطلاعات میتوانند با توجه به معیار طراحی و نیاز برنامه به هر عنصر هدفی وابسته باشند.
ایجاد و استفاده از صفات اختصاصی 4 مرحلهی زیر را شامل میشود:
- اعلان یک صفت اختصاصی
- ساخت این صفت اختصاصی
- استفاده از این صفت در یکی از عناصر هدف برنامه
- دسترسی به صفات از طریق انعکاس
در آخرین مرحله باید برنامهی سادهای را نوشت که بتواند جهت پیدا کردن نشان گذاریهای مختلف در میان متادیتاها به خواندن بپردازد. این برنامه به منظور دسترسی به صفات در زمان اجرا از انعکاسها استفاده میکند. به این موضوع در بخش بعد بیشتر خواهیم پرداخت.
اعلان یک صفت اختصاصی
یک صفت اختصاصی از کلاس System.Attribute حاصل میشود. برای مثال:
//a custom attribute BugFix to be assigned to a class and its members [AttributeUsage( AttributeTargets.Class | AttributeTargets.Constructor | AttributeTargets.Field | AttributeTargets.Method | AttributeTargets.Property, AllowMultiple = true)] public class DeBugInfo: System.Attribute
در این کد ما صفتی اختصاصی را به نام DeBugInfo اعلان کردهایم.
ساخت صفت اختصاصی
بیایید صفتی اختصاصی به نام DeBugInfo را بسازیم. به گونهای که کار این صفت ذخیرهسازی اطلاعات حاصل از رفع اشکال برنامه باشد. فرض کنید بخواهیم این صفت اطلاعات زیر را ذخیره کند:
- شمارهی کد اشکال
- اسم برنامهنویسی که اشکال برنامه را شناسایی کرده است
- تاریخ آخرین بازبینی کد
- یک پیام رشتهای برای ذخیرهسازی نکات برنامهنویس
کلاس DeBugInfo برای ذخیرهسازی سه مورد اول دارای سه ویژگی شخصی و برای ذخیرهسازی پیام دارای یک ویژگی عمومی است. بنابراین شمارهی اشکال، اسم برنامهنویس و تاریخ بازبینی پارامترهای مرتبهای کلاس DeBugInfo هستند و پیام یک پارامتر اسمی یا اختیاری است.
هر یک از صفات باید حداقل یک سازنده داشته باشد. پارامترهای مرتبهای باید از طریق این سازنده رد شوند. کد زیر کلاس DeBugInfo را نشان میدهد:
//a custom attribute BugFix to be assigned to a class and its members
[AttributeUsage(
AttributeTargets.Class |
AttributeTargets.Constructor |
AttributeTargets.Field |
AttributeTargets.Method |
AttributeTargets.Property,
AllowMultiple = true)]
public class DeBugInfo: System.Attribute {
private int bugNo;
private string developer;
private string lastReview;
public string message;
public DeBugInfo(int bg, string dev, string d) {
this.bugNo = bg;
this.developer = dev;
this.lastReview = d;
}
public int BugNo {
get {
return bugNo;
}
}
public string Developer {
get {
return developer;
}
}
public string LastReview {
get {
return lastReview;
}
}
public string Message {
get {
return message;
}
set {
message = value;
}
}
}
استفاده از صفت اختصاصی
با قرار دادن این صفت درست قبل از هدف آن، میتوان آن را به کار گرفت:
[DeBugInfo(45, "Zara Ali", "12/8/2012", Message = "Return type mismatch")]
[DeBugInfo(49, "Nuha Ali", "10/10/2012", Message = "Unused variable")]
class Rectangle {
//member variables
protected double length;
protected double width;
public Rectangle(double l, double w) {
length = l;
width = w;
}
[DeBugInfo(55, "Zara Ali", "19/10/2012", Message = "Return type mismatch")]
public double GetArea() {
return length * width;
}
[DeBugInfo(56, "Zara Ali", "19/10/2012")]
public void Display() {
Console.WriteLine("Length: {0}", length);
Console.WriteLine("Width: {0}", width);
Console.WriteLine("Area: {0}", GetArea());
}
}
در بخش بعدی اطلاعاتی در رابطه با استفاده از شیء کلاس انعکاس (Reflection) را بیان میکنیم.