PDA

View Full Version : مقاله: Attribute ها



Ali_Mor
جمعه 25 بهمن 1387, 23:56 عصر
به نام خدا
با اجازه اساتید قصد دارم در رابطه با Attribute ها مطالبی بیاورم. ممنون میشوم دوستان نظرات خود در رابطه با مقاله جهت اصلاح و تکمیل آن بیان کنند.

Attributeها
Attribute ها تگ های توصیفی هستند که اطلاعاتی اضافی در رابطه با عناصر برنامه نویسی فراهم می کنند. منظور از عناصر برنامه چیزهائی مانند کلاس، پروپرتی، فیلد و ... است.

کاربرد ؛ این اطلاعات اضافی در کجا بکار می آیند؟
بسته به نوع Attribute ها کاربرد آنها متفاوت است. بعضی از آنها اطلاعاتی در اختیار کامپایلر جهت نحوه برخورد آن می گذارند. بعضی برای IDE کاربرد دارند مثلا <Browsable> به IDE میفهماند که پروپرتی یا اونت صاحب این صفت در پنجره properties نشان داده شود یا خیر. در LINQ برای تعیین اطلاعات نگاشت بین کلاس های برنامه(Entity) و جداول بانک از Attributeها استفاده می شود.
برنامه نویس هم(منظور خودمان) می تواند اقدام به تعریف Attribute هایی برای مقاصد ویژه اش نماید.
نکاتی در رابطه با Attribute:
-شما می توانید یک یا چند Attribute را برای هر المان برنامه بکار ببرید اعم از اسمبلی، ماژول، کلاس ، پروپرتی ، متد و enum و ....
-در VB ، Attribute ها در < ... > قرار می گیرند. خصوصیات مختلف یک Attribute می تواند با کاما از یکدیگر جدا شوند . مثلاً
<Column(Storage:="_LastName", DbType:="NVarChar(20) NOT NULL", _
CanBeNull:=false)> _
-Attribute ها می توانند آرگومان بپذیرند. ارگومانها می تواند به دو روش ارسال گردد(این امر به تعریفAttribute نیز بستگی دارد)
1- به عنوان پارامترهای سازنده کلاس و به ترتیب تعریف شده

<CustomAttr(True, False)> Class Class1 2- با استفاده از نام آرگومانها(با استفاده از ":=" )(دیگر ترتیب آوردن آنها مهم نیست)

<CustomAttr(Update:=True, Keep:=False)> Class Class1 لازم بذکر است در زمانیکه سازنده کلاس Attribute(constructor of attribute classes) نیاز به آرگومان دارد باید آرگومانها بصورت ترتیبی(positional arguments)آورده شوند و آرگومانهای با نام (Named arguments) تنها برای مقدار دادن به فیلدها و پروپرتی های Attribute کاربرد دارند.(گیج نشوید، کمی صبر کنید متوجه خواهید شد که Attribute نیز یک کلاس است که می تواند سازنده، پروپرتی ، فیلد و حتی متد داشته باشد)
-آرگومانها می تواند اجباری یا اختیاری باشد.
نکته کوچک: Attribute و المان موصوف آن بایددر یک خط باشد ، اگر خواستید در دو خط بنویسید underline را فراموش نکنید.

مثال: Attribute های مشهور و پرکاربرد(البته از دید بنده)
<webMethod> : در وب سرویس ها، متدهائی را که باید قابل فراخوانی باشند (بطور علمی: براساس پروتکل SOAP قابل فراخوانی باشند) مشخص می کند.
<DllImport> برای فراخوانی کدهای unmanaged کاربرد دارد مثلا استفاده از dll ای که به زبان VB6 نوشته شدهاست.
<Browsable> همانطور که گفتیم مشخص می کند آیا پرو پرتی یا اونت باید در پنجره Properties ویژوال استادیو نمایش یابد یا خیر.
<Table> کاربرد در LINQ، برای نگاشت یک کلاس با جدولی در بانک
و ...

چطور یک Attribute مخصوص خود بسازیم؟
Attribute ها در واقع یک کلاس هستند که از System.Attribute ارث برده اند. عموماً Attribute ها دارای پروپرتی هایی هستند که توسط آنها اطلاعاتی را در رابطه با المانشان ذخیره می کنند. این اطلاعات هنگامی که قصد استفاده از Attribute را داریم بکار می آید.


Class TestAttribute
Inherits System.Attribute

Private m_SomeValue As String

Public Sub New(ByVal Value As String)
m_SomeValue = Value
End Sub
Public Sub Attr(ByVal AttrValue As String)
'Add method code here.
End Sub
Public Property SomeValue() As String ' A named parameter.
Get
Return m_SomeValue
End Get
Set(ByVal Value As String)
m_SomeValue = Value
End Set
End Property
End Class

بیائید با یک مثال کاربرد، تعریف و طریقه استفاده از Attribute را بررسی کنیم(این مثال فقط یک مثال است)

فرض کنید کلاس های مختلفی با فیلدهای گوناگون داریم که اطلاعات داخل آن فیلدها را باید در بانک وارد نمائیم. در هر کلاس توابعی داریم که وظیفه اعتبارسنجی (validation) فیلدها را بر عهده دارند. قبل از اینسرت داده های یک شی باید از معتبر بودن داده ها (فیلدها) مطمئن شویم یعنی تمام توابع اعتبارسنجی را فراخوانی نموده و در صورتی که همگی True برگردانند آنگاه اقدام به اینسرت داده های آن شی در بانک نمائیم.
راه اول: در هر کلاس تابعی بنویسیم که تمام توابع اعتبارسنجی را فراخوانی نموده و نتیجه آنها را بررسی نماید(All validation). راه حل بدی نیست، اما اگر بعد از نوشتن این تابع ، یک تابع اعتبارسنجی دیگر نوشتیم و یادمان رفت آن را در تابع All validation فراخوانی کنیم چه می شود! در ضمن برای نوشتن یک روتین ثابت که همیشه قبل از اینسرت هر کلاسی رخ دهد و وظیفه اعتبارسنجی را عهده دار باشد کار ما سخت خواهد شد.

راه دوم: توابع مربوط به اعتبارسنجی کلاسها را با یک Attribute خاص مشخص کنیم. حال قبل از اینسرت هر شی ای از هر کلاسی، کافی است توابع آن را با Reflection استخراج نموده و آن هائی را که دارای Attribute خاص مورد نظر ما هستند فراخوانی Invoke نمائیم.
تعریف Attribute خاص خودمان:


Public Class MKHValidation
Inherits Attribute
'برای کار مثال ما چیز دیگری لازم نیست
End Class

مشخص کردن توابع اعتبارسنجی کلاس با Attribute خاص


Public Class testEntity

Public name As String
Public KodMeli As String
Public Age As Integer

<MKHValidation()> _
Public Function Name_Validation() As Boolean
If name.Length > 0 And name.Length < 30 Then
Return True
Else
Return False
End If
End Function

<MKHValidation()> _
Public Function KodMeli_Validation() As Boolean
'کد ملی ده کارکتر عددی است
If KodMeli.Length = 10 And IsNumeric(KodMeli) Then
Return True
Else
Return False
End If
End Function

<MKHValidation()> _
Public Function Age_Validation() As Boolean
If Age > 0 Then
Return True
Else
Return False
End If
End Function
End Class

نوشتن روالی که اعتبارسنجی هر شی ای از هر کلاسی را انجام میدهد:


''' <summary>
''' تمام متدهای مربوط به اعتبارسنجی یک شی فراخوانی می شود
''' </summary>
''' <param name="entity">شی مورد نظر</param>
Public Function ChechEntityValidation(ByVal entity As Object) As Boolean

Dim typEntity As Type = entity.GetType
'تمام متدهای شی را بدست می آوریم
Dim AllMethod() As MethodInfo = typEntity.GetMethods(BindingFlags.Instance Or _
BindingFlags.Public Or _
BindingFlags.NonPublic)


For Each metod As MethodInfo In AllMethod

'بررسی اینکه آیا متد صفت مورد نظر را دارد
Dim Atr As Attribute = Attribute.GetCustomAttribute(metod, GetType(MKHValidation))

If Atr IsNot Nothing Then

'فراخوانی متد
Dim result As Object
result = metod.Invoke(entity, Nothing)

If result <> True Then
Return False
End If

End If

Next

Return True

End Function



امیدوارم مفید واقع شود

faravani
سه شنبه 09 تیر 1388, 06:32 صبح
آقای مداح ضمن تشکر از اینکه به سوالات بنده پاسخ میدین مطالب نوشته شده شما بسیار عالیست واقعا ازتون تشکر میکنم

alireza_tavakol
شنبه 17 مرداد 1388, 15:50 عصر
با سلام و خسته نباشید

اگه زحمتی نیست کد های بالا رو به زبان #C هم بنویسید:خجالت::افسرده::گریه:

Ali_Mor
یک شنبه 18 مرداد 1388, 01:36 صبح
اگر زحمتش رو بکشید و در اختیار دوستان هم قرار بدید، کمک شایانی به بنده کرده اید
(با کمک لینک زیر)
http://www.developerfusion.com/tools/convert/vb-to-csharp/
(http://www.developerfusion.com/tools/convert/csharp-to-vb/)

alireza_tavakol
یک شنبه 18 مرداد 1388, 10:11 صبح
Public Class testEntity

Public name As String
Public KodMeli As String
Public Age As Integer

<MKHValidation()> _
Public Function Name_Validation() As Boolean
If name.Length > 0 And name.Length < 30 Then
Return True
Else
Return False
End If
End Function

<MKHValidation()> _
Public Function KodMeli_Validation() As Boolean
'کد ملی ده کارکتر عددی است
If KodMeli.Length = 10 And IsNumeric(KodMeli) Then
Return True
Else
Return False
End If
End Function

<MKHValidation()> _
Public Function Age_Validation() As Boolean
If Age > 0 Then
Return True
Else
Return False
End If
End Function
End Class



# public class testEntity
# {
#
# public string name;
# public string KodMeli;
# public int Age;
#
# [MKHValidation()]
# public bool Name_Validation()
# {
# if (name.Length > 0 & name.Length < 30) {
# return true;
# }
# else {
# return false;
# }
# }
#
# [MKHValidation()]
# public bool KodMeli_Validation()
# {
# //کد ملی ده کارکتر عددی است
# if (KodMeli.Length == 10 & Information.IsNumeric(KodMeli)) {
# return true;
# }
# else {
# return false;
# }
# }
#
# [MKHValidation()]
# public bool Age_Validation()
# {
# if (Age > 0) {
# return true;
# }
# else {
# return false;
# }
# }


البته فکر نکنم کیفیک خوبی داشته باشه

alireza_tavakol
یک شنبه 18 مرداد 1388, 10:13 صبح
''' <summary>
''' تمام متدهای مربوط به اعتبارسنجی یک شی فراخوانی می شود
''' </summary>
''' <param name="entity">شی مورد نظر</param>
Public Function ChechEntityValidation(ByVal entity As Object) As Boolean

Dim typEntity As Type = entity.GetType
'تمام متدهای شی را بدست می آوریم
Dim AllMethod() As MethodInfo = typEntity.GetMethods(BindingFlags.Instance Or _
BindingFlags.Public Or _
BindingFlags.NonPublic)


For Each metod As MethodInfo In AllMethod

'بررسی اینکه آیا متد صفت مورد نظر را دارد
Dim Atr As Attribute = Attribute.GetCustomAttribute(metod, GetType(MKHValidation))

If Atr IsNot Nothing Then

'فراخوانی متد
Dim result As Object
result = metod.Invoke(entity, Nothing)

If result <> True Then
Return False
End If

End If

Next

Return True

End Function





1. /// <summary>
2. /// تمام متدهای مربوط به اعتبارسنجی یک شی فراخوانی می شود
3. /// </summary>
4. /// <param name="entity">شی مورد نظر</param>
5. public bool ChechEntityValidation(object entity)
6. {
7.
8. Type typEntity = entity.GetType;
9. //تمام متدهای شی را بدست می آوریم
10. MethodInfo[] AllMethod = typEntity.GetMethods(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
11.
12.
13. foreach (MethodInfo metod in AllMethod) {
14.
15. //بررسی اینکه آیا متد صفت مورد نظر را دارد
16. Attribute Atr = Attribute.GetCustomAttribute(metod, typeof(MKHValidation));
17.
18. if (Atr != null) {
19.
20. //فراخوانی متد
21. object result = null;
22. result = metod.Invoke(entity, null);
23.
24. if (result != true) {
25. return false;
26.
27. }
28.
29. }
30. }
31.
32.
33. return true;
34. }