C # में एक कस्टम विशेषता कैसे बनाएँ


119

मैंने कई बार कोशिश की है लेकिन फिर भी मैं कस्टम विशेषताओं के उपयोग को समझने में सक्षम नहीं हूं (मैं पहले ही बहुत सारे लिंक से गुजर चुका हूं)।

क्या कोई मुझे कोड के साथ कस्टम विशेषता का एक बहुत ही मूल उदाहरण समझा सकता है?

जवाबों:


96

जबकि एक कस्टम विशेषता बनाने के लिए कोड काफी सरल है, यह बहुत महत्वपूर्ण है कि आप समझें कि क्या विशेषताएं हैं:

विशेषताएँ मेटाडेटा आपके प्रोग्राम में संकलित हैं। गुण स्वयं किसी वर्ग, संपत्ति या मॉड्यूल में कोई कार्यक्षमता नहीं जोड़ते हैं - केवल डेटा। हालांकि, प्रतिबिंब का उपयोग करके, कार्यक्षमता बनाने के लिए उन विशेषताओं का लाभ उठाया जा सकता है।

इसलिए, उदाहरण के लिए, Microsoft के एंटरप्राइज़ लाइब्रेरी से मान्यता आवेदन ब्लॉक को देखें । यदि आप एक कोड उदाहरण देखते हैं, तो आप देखेंगे:

    /// <summary>
    /// blah blah code.
    /// </summary>
    [DataMember]
    [StringLengthValidator(8, RangeBoundaryType.Inclusive, 8, RangeBoundaryType.Inclusive, MessageTemplate = "\"{1}\" must always have \"{4}\" characters.")]
    public string Code { get; set; }

ऊपर दिए गए स्निपेट से, कोई अनुमान लगा सकता है कि कोड हमेशा मान्य होगा, जब भी बदला जाता है, तो मान्यकर्ता के नियमों के अनुसार (उदाहरण में, कम से कम 8 वर्ण और अधिकतम 8 वर्ण हैं)। लेकिन सच्चाई यह है कि गुण कुछ भी नहीं करता है; जैसा कि पहले उल्लेख किया गया है, यह केवल संपत्ति में मेटाडेटा जोड़ता है।

हालाँकि, एंटरप्राइज़ लाइब्रेरी में एक Validation.Validateविधि है जो आपकी वस्तु पर गौर करेगी, और प्रत्येक संपत्ति के लिए, यह जाँच करेगी कि क्या सामग्री विशेषता द्वारा बताए गए नियम का उल्लंघन करती है।

तो, यह है कि आपको विशेषताओं के बारे में कैसे सोचना चाहिए - अपने कोड में डेटा जोड़ने का एक तरीका जो बाद में अन्य तरीकों / कक्षाओं / आदि द्वारा उपयोग किया जा सकता है।


क्या मुझे वास्तव में जवाब पसंद है और विशेष रूप से ", एक और सवाल मैं उपरोक्त कोड के सेट स्टेटमेंट में एक ही शर्त रख सकता हूं कि यह कैसे
आरोपों

1
@ स्लैश: क्या आप इसे फिर से परिभाषित कर सकते हैं? मुझे सवाल समझ में नहीं आया।
ब्रूनो ब्रांट

1
मुझे लगता है कि स्लैश का उपयोग विशेषताओं के बीच अंतर के बारे में पूछना और वास्तविक सत्यापन कोड को संपत्ति के सेटर के अंदर रखना है। उत्तर: मूल्य को मान्य करने के लिए सेटर के अंदर कोड लिखते समय, केवल विशेषताओं का उपयोग करके सत्यापन को निष्पादित नहीं किया जाएगा। विशेषताएँ सिर्फ "मेटा-डेटा" हैं। एक और कोड कहीं और आपके द्वारा उपयोग की जाने वाली विशेषताओं में दिलचस्पी होनी चाहिए, उन्हें पढ़ें और उन पर आधारित क्रियाएं करें। एक विशिष्ट उदाहरण एक मान्यता पुस्तकालय है, जैसा @BrunoBrant उल्लेख किया गया है।
रोमार

10
निश्चित नहीं कि यह स्वीकृत उत्तर क्यों है। वास्तविक प्रश्न (जो Google में अनुक्रमित है, साथ ही) " C # में एक कस्टम विशेषता कैसे बनाएं "। जवाब उस विषय में बिल्कुल नहीं है। दूसरा उत्तर दूसरी ओर करता है।
दक्रस्टार

मुझे लगता है कि दूसरा उत्तर प्रश्न से संबंधित है।
मोहम्मद ताहेरियन

267

आप एक वर्ग लिखकर शुरू करते हैं जो विशेषता से प्राप्त होता है :

public class MyCustomAttribute: Attribute
{
    public string SomeProperty { get; set; }
}

तब आप इस विशेषता के साथ कुछ भी (वर्ग, विधि, संपत्ति, ...) सजा सकते हैं:

[MyCustomAttribute(SomeProperty = "foo bar")]
public class Foo
{

}

और अंत में आप इसे लाने के लिए प्रतिबिंब का उपयोग करेंगे:

var customAttributes = (MyCustomAttribute[])typeof(Foo).GetCustomAttributes(typeof(MyCustomAttribute), true);
if (customAttributes.Length > 0)
{
    var myAttribute = customAttributes[0];
    string value = myAttribute.SomeProperty;
    // TODO: Do something with the value
}

आप लक्ष्य प्रकारों को सीमित कर सकते हैं जिनमें यह विशेषता विशेषता AttributUsage विशेषता का उपयोग करके लागू की जा सकती है :

/// <summary>
/// This attribute can only be applied to classes
/// </summary>
[AttributeUsage(AttributeTargets.Class)]
public class MyCustomAttribute : Attribute

विशेषताओं के बारे में जानने के लिए महत्वपूर्ण बातें:

  • विशेषताएँ मेटाडेटा हैं।
  • उन्हें विधानसभा में संकलन-समय पर बेक किया जाता है, जिसके बहुत गंभीर निहितार्थ हैं कि आप उनके गुणों को कैसे सेट कर सकते हैं। केवल निरंतर (संकलित समय में ज्ञात) मान स्वीकार किए जाते हैं
  • कस्टम विशेषताओं का कोई अर्थ और उपयोग करने का एकमात्र तरीका प्रतिबिंब का उपयोग करना है । इसलिए यदि आप उन्हें लाने के लिए रनटाइम पर प्रतिबिंब का उपयोग नहीं करते हैं और कस्टम विशेषता के साथ कुछ सजाने के लिए बहुत कुछ होने की उम्मीद नहीं है।
  • विशेषताओं के निर्माण का समय गैर-निर्धारक है। वे सीएलआर द्वारा त्वरित हैं और आपका इस पर पूर्ण नियंत्रण नहीं है।

3
कहां, किस फंक्शन / क्लास में, क्या मैं इसे लाने के लिए रिफ्लेक्शन का इस्तेमाल करूंगी
हसन ए यूसेफ

@ हासन ए यूसेफ, उदाहरण के लिए एंटिटी फ्रेमवर्क में "की" विशेषता है जो फ्रेमवर्क को कहते हैं: इस संपत्ति को प्राथमिक कुंजी के रूप में माना जाना चाहिए। ORM बनाने में, विशेषताएँ बहुत उपयोगी हैं
परसा

आप एक संपत्ति पर एक कस्टम विशेषता का उपयोग कैसे करते हैं और एक वर्ग नहीं?
कैनवस

docs.microsoft.com/en-us/dotnet/standard/attributes/… सिर्फ पूर्णता के लिए, यह msdn पेज इसे बहुत अच्छी तरह से सारांशित करता है
Barış Akkurt

जेनेरिक के साथ, यह बहुत आसान है, प्रकार प्राप्त करने के लिए बहुत आसान है:var value = typeof(Foo).GetCustomAttributes<MyCustomAttribute>().First().SomeProperty;
jpaugh

27

डैरिन दिमित्रोव की शानदार प्रतिक्रिया का उपयोग / नकल करना , यह है कि किसी संपत्ति पर कस्टम विशेषता का उपयोग कैसे किया जाए और वर्ग नहीं:

सजी हुई संपत्ति [वर्ग Foo]:

[MyCustomAttribute(SomeProperty = "This is a custom property")]
public string MyProperty { get; set; }

इसे प्राप्त करना:

PropertyInfo propertyInfo = typeof(Foo).GetProperty(propertyToCheck);
object[] attribute = propertyInfo.GetCustomAttributes(typeof(MyCustomAttribute), true);
if (attribute.Length > 0)
{
    MyCustomAttribute myAttribute = (MyCustomAttribute)attribute[0];
    string propertyValue = myAttribute.SomeProperty;
}

आप इसे एक लूप में फेंक सकते हैं और कक्षा की प्रत्येक संपत्ति पर इस कस्टम विशेषता तक पहुंचने के लिए प्रतिबिंब का उपयोग कर सकते हैं Foo:

foreach (PropertyInfo propertyInfo in Foo.GetType().GetProperties())
{
    string propertyName = propertyInfo.Name;

    object[] attribute = propertyInfo.GetCustomAttributes(typeof(MyCustomAttribute), true);
    // Just in case you have a property without this annotation
    if (attribute.Length > 0)
    {
        MyCustomAttribute myAttribute = (MyCustomAttribute)attribute[0];
        string propertyValue = myAttribute.SomeProperty;
        // TODO: whatever you need with this propertyValue
    }
}

मेजर थैंक यू, डारिन !!


यदि हम नहीं जानते कि किसी संपत्ति पर किस प्रकार के गुण मौजूद हैं, तो हम इसका विस्तार कैसे करेंगे? object[] attribute = propertyInfo.GetCustomAttributes(typeof(???), true);मैं बस उन सभी पर पुनरावृति करना चाहता हूं और m1()प्रत्येक अज्ञात विशेषता का एक तरीका
कहता हूं

0

संक्षिप्त उत्तर c # में एक विशेषता बनाने के लिए है, आपको केवल इसे एट्रिब्यूट क्लास से इनहेरिट करने की आवश्यकता है, बस यह :)

लेकिन यहाँ मैं विस्तार से विशेषताएँ बताने जा रहा हूँ:

मूल रूप से विशेषताएँ वे कक्षाएं हैं जिनका उपयोग हम अपने तर्क को विधानसभाओं, कक्षाओं, विधियों, गुणों, क्षेत्रों, ...

.Net में, Microsoft ने कुछ पूर्वनिर्धारित विशेषताएँ प्रदान की हैं जैसे कि अप्रचलित या सत्यापन विशेषताएँ जैसे ([आवश्यक], [StringLength (१००)]], [श्रेणी (०, ९९९९९९९९,)), हमारे पास Asp.net में ActionFilters जैसे गुण भी हैं। हमारे कोड्स के लिए हमारे वांछित तर्क को लागू करने के लिए यह बहुत उपयोगी हो सकता है ( यदि आप इसे सीखना चाहते हैं, तो एक्शन फिल्टर के बारे में यह लेख पढ़ें )

एक और बिंदु, आप AttibuteUsage के माध्यम से अपनी विशेषता पर एक प्रकार का कॉन्फ़िगरेशन लागू कर सकते हैं।

  [AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct, AllowMultiple = true)]

जब आप एट्रीब्यूट्स के साथ एक विशेषता वर्ग को सजाते हैं, तो आप ग # संकलक को बता सकते हैं कि मैं इस विशेषता का उपयोग करने जा रहा हूं: मैं इसका उपयोग कक्षाओं पर, संपत्तियों पर विधानसभाओं पर या ... पर करने जा रहा हूं और मेरी विशेषता का उपयोग करने की अनुमति है परिभाषित लक्ष्यों (कक्षाओं, विधानसभाओं, गुणों, ...) पर कई बार या नहीं ?!

विशेषताओं के बारे में इस परिभाषा के बाद मैं आपको एक उदाहरण दिखाने जा रहा हूं: कल्पना करें कि हम विश्वविद्यालय में एक नए पाठ को परिभाषित करना चाहते हैं और हम अपने विश्वविद्यालय में नए प्रवेश, ओके को परिभाषित करने के लिए सिर्फ प्रवेश और स्वामी की अनुमति देना चाहते हैं?

namespace ConsoleApp1
{
    /// <summary>
    /// All Roles in our scenario
    /// </summary>
    public enum UniversityRoles
    {
        Admin,
        Master,
        Employee,
        Student
    }

    /// <summary>
    /// This attribute will check the Max Length of Properties/fields
    /// </summary>
    [AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct, AllowMultiple = true)]
    public class ValidRoleForAccess : Attribute
    {
        public ValidRoleForAccess(UniversityRoles role)
        {
            Role = role;
        }
        public UniversityRoles Role { get; private set; }

    }


    /// <summary>
    /// we suppose that just admins and masters can define new Lesson
    /// </summary>
    [ValidRoleForAccess(UniversityRoles.Admin)]
    [ValidRoleForAccess(UniversityRoles.Master)]
    public class Lesson
    {
        public Lesson(int id, string name, DateTime startTime, User owner)
        {
            var lessType = typeof(Lesson);
            var validRolesForAccesses = lessType.GetCustomAttributes<ValidRoleForAccess>();

            if (validRolesForAccesses.All(x => x.Role.ToString() != owner.GetType().Name))
            {
                throw new Exception("You are not Allowed to define a new lesson");
            }
            
            Id = id;
            Name = name;
            StartTime = startTime;
            Owner = owner;
        }
        public int Id { get; private set; }
        public string Name { get; private set; }
        public DateTime StartTime { get; private set; }

        /// <summary>
        /// Owner is some one who define the lesson in university website
        /// </summary>
        public User Owner { get; private set; }

    }

    public abstract class User
    {
        public int Id { get; set; }
        public string Name { get; set; }
        public DateTime DateOfBirth { get; set; }
    }


    public class Master : User
    {
        public DateTime HireDate { get; set; }
        public Decimal Salary { get; set; }
        public string Department { get; set; }
    }

    public class Student : User
    {
        public float GPA { get; set; }
    }



    class Program
    {
        static void Main(string[] args)
        {

            #region  exampl1

            var master = new Master()
            {
                Name = "Hamid Hasani",
                Id = 1,
                DateOfBirth = new DateTime(1994, 8, 15),
                Department = "Computer Engineering",
                HireDate = new DateTime(2018, 1, 1),
                Salary = 10000
            };
            var math = new Lesson(1, "Math", DateTime.Today, master);

            #endregion

            #region exampl2
            var student = new Student()
            {
                Name = "Hamid Hasani",
                Id = 1,
                DateOfBirth = new DateTime(1994, 8, 15),
                GPA = 16
            };
            var literature = new Lesson(2, "literature", DateTime.Now.AddDays(7), student);
            #endregion

            ReadLine();
        }
    }


}

प्रोग्रामिंग की वास्तविक दुनिया में शायद हम विशेषताओं का उपयोग करने के लिए इस दृष्टिकोण का उपयोग नहीं करते हैं और मैंने विशेषताओं के उपयोग में इसके शैक्षिक बिंदु के कारण यह कहा है

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.