खोज…
एक कस्टम विशेषता बनाना
//1) All attributes should be inherited from System.Attribute
//2) You can customize your attribute usage (e.g. place restrictions) by using System.AttributeUsage Attribute
//3) You can use this attribute only via reflection in the way it is supposed to be used
//4) MethodMetadataAttribute is just a name. You can use it without "Attribute" postfix - e.g. [MethodMetadata("This text could be retrieved via reflection")].
//5) You can overload an attribute constructors
[System.AttributeUsage(System.AttributeTargets.Method | System.AttributeTargets.Class)]
public class MethodMetadataAttribute : System.Attribute
{
//this is custom field given just for an example
//you can create attribute without any fields
//even an empty attribute can be used - as marker
public string Text { get; set; }
//this constructor could be used as [MethodMetadata]
public MethodMetadataAttribute ()
{
}
//This constructor could be used as [MethodMetadata("String")]
public MethodMetadataAttribute (string text)
{
Text = text;
}
}
एक विशेषता का उपयोग करना
[StackDemo(Text = "Hello, World!")]
public class MyClass
{
[StackDemo("Hello, World!")]
static void MyMethod()
{
}
}
एक विशेषता पढ़ना
विधि GetCustomAttributes
सदस्य पर लागू कस्टम विशेषताओं की एक सरणी देता है। इस सरणी को प्राप्त करने के बाद आप एक या अधिक विशिष्ट विशेषताओं की खोज कर सकते हैं।
var attribute = typeof(MyClass).GetCustomAttributes().OfType<MyCustomAttribute>().Single();
या उनके माध्यम से पुनरावृति
foreach(var attribute in typeof(MyClass).GetCustomAttributes()) {
Console.WriteLine(attribute.GetType());
}
System.Reflection.CustomAttributeExtensions
से GetCustomAttribute
एक्सटेंशन विधि एक निर्दिष्ट प्रकार की एक कस्टम विशेषता को पुनः प्राप्त करती है, इसे किसी भी MemberInfo
लिए लागू किया जा सकता है।
var attribute = (MyCustomAttribute) typeof(MyClass).GetCustomAttribute(typeof(MyCustomAttribute));
GetCustomAttribute
को खोजने के लिए विशेषता के प्रकार को निर्दिष्ट करने के लिए सामान्य हस्ताक्षर भी हैं।
var attribute = typeof(MyClass).GetCustomAttribute<MyCustomAttribute>();
बूलियन तर्क inherit
उन तरीकों के दोनों के लिए पारित किया जा सकता है। यदि तत्व के true
पूर्वजों के लिए निर्धारित यह मान भी निरीक्षण किया जाएगा।
DebuggerDisplay विशेषता
DebuggerDisplay
एट्रीब्यूट जोड़ने से DebuggerDisplay
के वर्ग को प्रदर्शित करने के तरीके को बदल दिया जाएगा, जब यह ऊपर मँडरा जाता है।
{}
में लिपटे अभिव्यक्तियों का मूल्यांकन डिबगर द्वारा किया जाएगा। यह निम्नलिखित नमूने या अधिक जटिल तर्क की तरह एक साधारण संपत्ति हो सकती है।
[DebuggerDisplay("{StringProperty} - {IntProperty}")]
public class AnObject
{
public int ObjectId { get; set; }
public string StringProperty { get; set; }
public int IntProperty { get; set; }
}
समापन ब्रैकेट से पहले ,nq
जोड़ना ,nq
स्ट्रिंग को आउटपुट करते समय उद्धरण हटाता है।
[DebuggerDisplay("{StringProperty,nq} - {IntProperty}")]
हालांकि {}
में सामान्य अभिव्यक्तियों की अनुमति नहीं है। DebuggerDisplay
विशेषता को विधानसभा मेटाडेटा में एक स्ट्रिंग के रूप में लिखा जाएगा। वैधता के लिए {}
में अभिव्यक्त नहीं किए गए हैं। तो एक DebuggerDisplay
विशेषता जिसमें अधिक जटिल तर्क होता है अर्थात कुछ सरल अंकगणित C # में ठीक काम कर सकते हैं, लेकिन VB.NET में मूल्यांकन की गई समान अभिव्यक्ति संभवतः वाक्यविन्यास रूप से मान्य नहीं होगी और डीबग करते समय त्रुटि उत्पन्न करती है।
DebuggerDisplay
अधिक भाषा अज्ञेय बनाने का एक तरीका है कि एक विधि या संपत्ति में अभिव्यक्ति लिखना और इसके बजाय इसे कॉल करना।
[DebuggerDisplay("{DebuggerDisplay(),nq}")]
public class AnObject
{
public int ObjectId { get; set; }
public string StringProperty { get; set; }
public int IntProperty { get; set; }
private string DebuggerDisplay()
{
return $"{StringProperty} - {IntProperty}"";
}
}
सभी चाहते हैं कि DebuggerDisplay
सभी या बस कुछ गुणों का उत्पादन करे और जब डिबगिंग और निरीक्षण भी वस्तु का प्रकार हो।
नीचे दिया गया उदाहरण #if DEBUG
साथ सहायक विधि को भी घेरता है क्योंकि DebuggerDisplay
का उपयोग डिबगिंग वातावरण में किया जाता है।
[DebuggerDisplay("{DebuggerDisplay(),nq}")]
public class AnObject
{
public int ObjectId { get; set; }
public string StringProperty { get; set; }
public int IntProperty { get; set; }
#if DEBUG
private string DebuggerDisplay()
{
return
$"ObjectId:{this.ObjectId}, StringProperty:{this.StringProperty}, Type:{this.GetType()}";
}
#endif
}
कॉलर जानकारी विशेषताएँ
आह्वान करने की विधि के बारे में जानकारी को पास करने के लिए कॉलर जानकारी विशेषताओं का उपयोग किया जा सकता है। घोषणा इस तरह दिखती है:
using System.Runtime.CompilerServices;
public void LogException(Exception ex,
[CallerMemberName]string callerMemberName = "",
[CallerLineNumber]int callerLineNumber = 0,
[CallerFilePath]string callerFilePath = "")
{
//perform logging
}
और आह्वान इस तरह दिखता है:
public void Save(DBContext context)
{
try
{
context.SaveChanges();
}
catch (Exception ex)
{
LogException(ex);
}
}
ध्यान दें कि केवल पहला पैरामीटर LogException
विधि को स्पष्ट रूप से पारित किया गया है, जबकि उनमें से बाकी को प्रासंगिक मूल्यों के साथ संकलन समय पर प्रदान किया जाएगा।
callerMemberName
पैरामीटर को "Save"
मान - कॉलिंग विधि का नाम प्राप्त होगा।
callerLineNumber
पैरामीटर को LogException
विधि कॉल की संख्या प्राप्त होगी, जिस पर LogException
विधि कॉल लिखा गया है।
और 'callerFilePath' पैरामीटर को फ़ाइल का पूरा पथ प्राप्त होगा विधि Save
में घोषित किया गया है।
इंटरफ़ेस से एक विशेषता पढ़ना
एक इंटरफ़ेस से विशेषताओं को प्राप्त करने का कोई सरल तरीका नहीं है, क्योंकि कक्षाएं एक इंटरफ़ेस से विशेषता प्राप्त नहीं करती हैं। जब भी एक इंटरफ़ेस को लागू करने या एक व्युत्पन्न वर्ग में सदस्यों को ओवरराइड करने पर, आपको विशेषताओं को फिर से घोषित करने की आवश्यकता होती है। इसलिए नीचे दिए गए उदाहरण में आउटपुट तीनों मामलों में True
होगा।
using System;
using System.Linq;
using System.Reflection;
namespace InterfaceAttributesDemo {
[AttributeUsage(AttributeTargets.Interface, Inherited = true)]
class MyCustomAttribute : Attribute {
public string Text { get; set; }
}
[MyCustomAttribute(Text = "Hello from interface attribute")]
interface IMyClass {
void MyMethod();
}
class MyClass : IMyClass {
public void MyMethod() { }
}
public class Program {
public static void Main(string[] args) {
GetInterfaceAttributeDemo();
}
private static void GetInterfaceAttributeDemo() {
var attribute1 = (MyCustomAttribute) typeof(MyClass).GetCustomAttribute(typeof(MyCustomAttribute), true);
Console.WriteLine(attribute1 == null); // True
var attribute2 = typeof(MyClass).GetCustomAttributes(true).OfType<MyCustomAttribute>().SingleOrDefault();
Console.WriteLine(attribute2 == null); // True
var attribute3 = typeof(MyClass).GetCustomAttribute<MyCustomAttribute>(true);
Console.WriteLine(attribute3 == null); // True
}
}
}
इंटरफ़ेस विशेषताओं को पुनर्प्राप्त करने का एक तरीका उनके लिए एक वर्ग द्वारा लागू किए गए सभी इंटरफेस के माध्यम से खोज करना है।
var attribute = typeof(MyClass).GetInterfaces().SelectMany(x => x.GetCustomAttributes().OfType<MyCustomAttribute>()).SingleOrDefault();
Console.WriteLine(attribute == null); // False
Console.WriteLine(attribute.Text); // Hello from interface attribute
अप्रचलित गुण
System.Obirect एक विशेषता है जिसका उपयोग किसी प्रकार या ऐसे सदस्य को चिह्नित करने के लिए किया जाता है जिसका एक बेहतर संस्करण है, और इस प्रकार इसका उपयोग नहीं किया जाना चाहिए।
[Obsolete("This class is obsolete. Use SomeOtherClass instead.")]
class SomeClass
{
//
}
यदि उपरोक्त वर्ग का उपयोग किया जाता है, तो संकलक चेतावनी देगा "यह वर्ग अप्रचलित है। इसके बजाय SomeOtherClass का उपयोग करें।"