2010-04-15 4 views
12

हाल ही में question एमवीसी विशेषताओं के बारे में, किसी ने पूछा कि क्या एक एक्शन विधि पर एचटीपीपोस्ट और एचटीपीडीलेट गुणों का उपयोग करना होगा या तो अनुरोध प्रकार की अनुमति दी जा रही है या कोई अनुरोध नहीं किया जा रहा है (क्योंकि यह दोनों पोस्ट और डिलीट नहीं हो सकता है उसी समय)। मैंने देखा है कि ActionMethodSelectorAttribute, जो HttpPostAttribute और HttpDeleteAttribute से दोनों निकाले जाते हैं साथएक अमूर्त विशेषता वर्ग पर AllowMultiple = false को इंगित करने का क्या मतलब है?

[AttributeUsage(AttributeTargets.Method, 
       AllowMultiple = false, 
       Inherited = true)] 

मैं उम्मीद थी यह इस वजह से एक ही विधि पर अनुमति नहीं करने के लिए दोनों HttpPost और HttpDelete सजाया है, लेकिन संकलक शिकायत नहीं है। मेरा सीमित परीक्षण मुझे बताता है कि बेस क्लास पर विशेषता उपयोग को अनदेखा किया जाता है। अनुमति दें कई अलग-अलग में से केवल किसी विधि/वर्ग पर लागू होने से विशेषता को अस्वीकार करते हैं और ऐसा नहीं लगता है कि वे गुण उसी वर्ग से प्राप्त होते हैं जो गुणकों को अनुमति देने के लिए कॉन्फ़िगर नहीं किया गया है। इसके अलावा, बेस क्लास पर विशेषता उपयोग आपको व्युत्पन्न वर्ग पर विशेषता उपयोग को बदलने से भी रोकता नहीं है। यह मामला है, आधार विशेषता वर्ग पर मूल्यों को भी सेट करने का क्या मतलब है? क्या यह सिर्फ सलाहकार है या क्या मैं कुछ काम करता हूं कि वे कैसे काम करते हैं?

एफवाईआई - यह पता चला है कि दोनों का उपयोग मूल रूप से उस विधि को कभी भी माना जा रहा है। विशेषताओं का मूल्यांकन स्वतंत्र रूप से किया जाता है और उनमें से एक हमेशा यह संकेत देगा कि विधि अनुरोध के लिए मान्य नहीं है क्योंकि यह एक साथ पोस्ट और डिलीट दोनों नहीं हो सकती है।

उत्तर

8

आधार विशेषता पर AllowMultiple सेट करना अनिवार्य रूप से उन सभी विशेषताओं के लिए डिफ़ॉल्ट सेट करता है जो इससे प्राप्त होते हैं। यदि आप कई उदाहरणों को अनुमति देने के लिए बेस एट्रिब्यूट से प्राप्त सभी विशेषताओं को चाहते थे तो आप सभी व्युत्पन्न विशेषताओं के लिए ऐसा करने से बचने के लिए मूल विशेषता के लिए [AttributeUsage] विशेषता लागू करके डुप्लिकेशन सहेज सकते हैं। कई उदाहरणों की अनुमति नहीं देते कस्टम विशेषताओं के बाद से डिफ़ॉल्ट रूप से,

public abstract class MyAttributeBase : Attribute 
{ 
} 

public sealed class FooAttribute : MyAttributeBase 
{ 
} 

public sealed class BarAttribute : MyAttributeBase 
{ 
} 

[Foo] 
[Foo] 
[Bar] 
[Bar] 
public class A 
{ 
} 

यह खड़ा के रूप में, यह एक संकलक त्रुटि उत्पन्न करता है,:

उदाहरण के लिए, आप इसकी अनुमति देना चाहते थे लगता है। अब, आप [Foo] दोनों और [Bar] इस तरह के लिए एक [AttribteUsage] लागू हो सकते हैं:

[AttributeUsage(AttributeTargets.Class, AllowMultiple = true)] 
public sealed class FooAttribute : MyAttributeBase 
{ 
} 

[AttributeUsage(AttributeTargets.Class, AllowMultiple = true)] 
public sealed class BarAttribute : MyAttributeBase 
{ 
} 

लेकिन वैकल्पिक रूप से, आप के बजाय सिर्फ यह आधार विशेषता पर लागू हो सकते:

[AttributeUsage(AttributeTargets.Class, AllowMultiple = true)] 
public abstract class MyAttributeBase : Attribute 
{ 
} 

public sealed class FooAttribute : MyAttributeBase 
{ 
} 

public sealed class BarAttribute : MyAttributeBase 
{ 
} 

दोनों दृष्टिकोण एक ही सीधा प्रभाव ([Foo] और [Bar] दोनों के कई उदाहरणों की अनुमति है) लेकिन दूसरे दृष्टिकोण पर अप्रत्यक्ष प्रभाव भी है कि कोई भी[MyAttribute] से प्राप्त अन्य विशेषताओं को अब तक कई उदाहरणों की अनुमति नहीं दी जाएगी उनके पास [AttributeUsage] है जो उस सेटिंग को ओवरराइड करता है।

+0

उनका मुद्दा यह है कि एक से अधिक की अनुमति AllowAultiple = झूठी जब MyAttributeBase की अनुमति है। तो आपको केवल एक ही [फू] या [बार] की अनुमति होगी। – Rangoric

+0

.NET में ऐसा करने का कोई तरीका नहीं है, क्योंकि प्रश्नकर्ता ने प्रश्न में खोज की और स्पष्ट किया। मैं इस सवाल को संबोधित कर रहा था कि "हम कभी भी एट्रिब्यूट यूज को बेस एट्रिब्यूट में क्यों लागू करेंगे?" –

0

अनुमति एकाधिक अनुमति देता है/उस विशिष्ट विशेषता को एक से अधिक बार उपयोग करने की अनुमति देता है। इसका कोई प्रभाव नहीं पड़ता कि इसके साथ अन्य विशेषताओं को जोड़ा जा सकता है या नहीं।

इसलिए उदाहरण के लिए, यदि आप एक ObfuscationAttribute को नियंत्रित करता है कि विधि का नाम सक्षम या अक्षम है या नहीं है, तो आप नहीं उपयोगकर्ताओं को ऐसा करने में सक्षम होना चाहते हैं: इस मामले में

[Obfuscation("DisableRenaming")] 
[Obfuscation("EnableRenaming")] 
void MyMethod() 
{ 
} 

कहानियो को नहीं किया जा सकता सक्षम और अक्षम दोनों, इसलिए आप यह सुनिश्चित करने के लिए AllowMultiple = false का उपयोग करेंगे कि विधि केवल इस विशेष विशेषता के साथ चिह्नित की गई है।

आप अपने परस्पर-अनन्य मामले में, कल्पित रूप से क्या कर सकते हैं, HttpSettings नामक एक विशेषता का उपयोग करते हैं, जिसने एक पैरामीटर संकेत दिया है कि यह पोस्ट या हटाएं "मोड" पर लागू होता है या नहीं। इसके बाद विकल्पों की आपसी विशिष्टता को लागू करने के लिए अनुमति दें एकाधिक = झूठी।

+0

आपकी व्याख्या पहले से ही प्रश्न का हिस्सा है। प्रस्ताव को कोड के स्वामित्व की आवश्यकता है। मूल प्रश्न विरासत के बारे में है। –

+0

पहले से ही एक AcceptVerbsAttribute है जो आप वास्तव में वर्णन करते हैं। जैसा कि @ हेनक इंगित करता है, मुझे इसमें दिलचस्पी है कि बेस क्लास विशेषता उपयोग कैसे खेलता है, बिल्कुल भी। – tvanfosson

+0

ठीक है, क्षमा करें - मैंने आपके प्रश्न का गलत व्याख्या किया। –

0

की एक छोटी परीक्षण करते हैं:

using System; 
using System.Text; 
using System.Collections.Generic; 
using System.Linq; 
using Microsoft.VisualStudio.TestTools.UnitTesting; 
using System.Reflection; 

namespace TestAttrs { 
    public abstract class BaseAttribute : Attribute { 
     public string text; 
    } 

    [AttributeUsage(AttributeTargets.Method, AllowMultiple = true, Inherited = true)] 
    public class MultipleInheritedAttribute : BaseAttribute { } 

    [AttributeUsage(AttributeTargets.Method, AllowMultiple = true, Inherited = false)] 
    public class MultipleNonInheritedAttribute : BaseAttribute { } 

    [AttributeUsage(AttributeTargets.Method, AllowMultiple = false, Inherited = true)] 
    public class SingleInheritedAttribute : BaseAttribute { } 

    [AttributeUsage(AttributeTargets.Method, AllowMultiple = false, Inherited = false)] 
    public class SingleNonInheritedAttribute : BaseAttribute { } 

    public class BaseClass { 
     [MultipleInherited(text = "MultipleInheritedBase")] 
     [MultipleNonInherited(text = "MultipleNonInheritedBase")] 
     [SingleInherited(text = "SingleInheritedBase")] 
     [SingleNonInherited(text = "SingleNonInheritedBase")] 
     public virtual void Method() { ; } 
    } 

    public class DerivedClass : BaseClass { 
     [MultipleInherited(text = "MultipleInheritedDerived")] 
     [MultipleNonInherited(text = "MultipleNonInheritedDerived")] 
     [SingleInherited(text = "SingleInheritedDerived")] 
     [SingleNonInherited(text = "SingleNonInheritedDerived")] 
     public override void Method() { 
      base.Method(); 
     } 
    } 

    [TestClass] 
    public class AttributesTest { 
     [TestMethod] 
     public void TestAttributes() { 
      MemberInfo mi = typeof(DerivedClass).GetMember("Method")[0]; 
      object[] attrs = mi.GetCustomAttributes(true); 

      string log = ""; 
      foreach(BaseAttribute attr in attrs) { 
       log += attr.text+"|"; 
      } 
      Assert.AreEqual("MultipleInheritedDerived|SingleInheritedDerived|SingleNonInheritedDerived|MultipleNonInheritedDerived|MultipleInheritedBase|", log); 
     } 
    } 
} 

आप देख सकते हैं, विशेषता Inherted=true चिह्नित है तो यह व्युत्पन्न वर्ग के लिए वापस कर दी जाएगी, लेकिन अगर विरासत में मिला विधि एक ही विशेषता के साथ चिह्नित है यदि - यह हो जाएगा AllowMultiple=false पर दबाया गया। तो - हमारे परीक्षण में, लॉग स्ट्रिंग में "एकाधिक इन्टरेटेड डेरिव" और "एकाधिक इन्टरनेटबेस" दोनों शामिल हैं, लेकिन "सिंगल इनहेरिटबेसबेस" नहीं।

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

इसके अलावा, कृपया ध्यान दें कि कोड लेने वाली विशेषताओं:

 object[] attrs = mi.GetCustomAttributes(true); 

यह बताता है कि यह विरासत में मिला विशेषताओं में रुचि रखता है। यदि

 object[] attrs = mi.GetCustomAttributes(false); 

तो परिणाम में उनकी उपयोग सेटिंग के बावजूद 4 विशेषताएँ होंगी। तो डेवलपर के लिए विरासत विशेषता उपयोग सेटिंग को अनदेखा करना संभव है।

+0

मेरी समस्या यह नहीं थी कि विधियों पर विशेषताओं को कैसे लागू किया जाता है, लेकिन मूल विशेषता में एक विशेषता का उपयोग क्यों होता है जो कोई फर्क नहीं पड़ता। आप वास्तव में एक ActionMethodSelectorAttribute लागू नहीं कर सकते क्योंकि यह सार है। आपको इसके बच्चों में से एक को लागू करना होगा। GuarantMultiple = सार आधार विशेषता पर झूठी कोई फर्क नहीं पड़ता क्योंकि आप आधार विशेषता के कई बच्चे विशेषताओं को तब तक लागू कर सकते हैं जब तक कि वे विभिन्न व्युत्पन्न प्रकारों के होते हैं। विशेषता लागू करने के लिए आपके उदाहरण के लिए बेसएट्रिब्यूट पर लागू होना आवश्यक है। – tvanfosson

+0

@tvanfosson अब मैं अंत में देखता हूं कि आपका क्या मतलब है। अनुमति दें एकाधिक एक ही अंतिम विशेषता प्रकार के उदाहरण निर्दिष्ट करता है, न कि इसकी मूल श्रेणी। कई उपयोगों के लिए यह एक पूर्ण ज्ञान बनाता है। इस विशेष मामले में यह बेकार है, लेकिन फिर भी आपको मार्गदर्शन करेगा यदि उदाहरण के लिए, आप अपने स्वयं के गैर-अमूर्त वंशज को ActionMethodSelectorAttribute से बना देंगे - कुछ ऐसा है [HttpMethod (HttpMethod.Post)] –

संबंधित मुद्दे