2012-01-11 37 views
22

मैं एक उदाहरण वर्गकैसे करता है, तो विधि एक विशेषता

public class MyClass{ 

    ActionResult Method1(){ 
     .... 
    } 

    [Authorize] 
    ActionResult Method2(){ 
     .... 
    } 

    [Authorize]  
    ActionResult Method3(int value){ 
     .... 
    } 

} 

है अब मैं क्या चाहते हैं एक समारोह लौटने सही/गलत है कि इस

var controller = new MyClass(); 

Assert.IsFalse(MethodHasAuthorizeAttribute(controller.Method1)); 
Assert.IsTrue(MethodHasAuthorizeAttribute(controller.Method2)); 
Assert.IsTrue(MethodHasAuthorizeAttribute(controller.Method3)); 

मैं की तरह क्रियान्वित किया जा सकता लिखने के लिए है की जाँच करने के उस बिंदु पर पहुंचे जहां

public bool MethodHasAuthorizeAttribute(Func<int, ActionResult> function) 
{ 
    return function.Method.GetCustomAttributes(typeof(AuthorizeAttribute), false).Length > 0; 
} 

विधि 3 के लिए काम करेगा। अब मैं इस जेनेरिक तरीके से ऐसा कैसे कर सकता हूं कि यह तारों और वर्गों को पैरामीटर के रूप में भी ले जाएगा?

+0

क्या आप यह जांचना चाहते हैं कि कक्षा, विधि या संपत्ति में एक सामान्य विधि के भीतर ऐसी विशेषता है या नहीं? –

+0

क्या आप यह जानना चाहते हैं कि किसी विधि के पास एक निश्चित प्रकार की विशेषता है या नहीं? – Rajesh

+0

मैं यह जांचना चाहता हूं कि विधि में एक विशेष विशेषता सेट है या नहीं, लेकिन मैं एक स्ट्रिंग के रूप में एक विधि नाम पास नहीं करना चाहता हूं। – 4rchie

उत्तर

20

आपके कोड के साथ समस्या public bool MethodHasAuthorizeAttribute(Func<int, ActionResult> function) का हस्ताक्षर है। MethodHasAuthorizeAttribute केवल आपके द्वारा निर्दिष्ट प्रतिनिधि के हस्ताक्षर से मेल खाते तर्कों के साथ उपयोग किया जा सकता है। इस मामले में को int के पैरामीटर के साथ ActionResult लौटने का एक तरीका।

जब आप इस विधि को MethodHasAuthorizeAttribute(controller.Method3) कहते हैं, तो कंपाइलर एक विधि समूह रूपांतरण करेगा। यह हमेशा वांछित नहीं हो सकता है और अप्रत्याशित परिणाम उत्पन्न कर सकता है (विधि समूह रूपांतरण हमेशा straigthforward नहीं हैं)। यदि आप MethodHasAuthorizeAttribute(controller.Method1) पर कॉल करने का प्रयास करते हैं तो आपको एक कंपाइलर त्रुटि मिलेगी क्योंकि कोई रूपांतरण नहीं है।

अभिव्यक्ति पेड़ों और प्रसिद्ध "विधिऑफ" चाल के साथ एक और सामान्य समाधान बनाया जा सकता है। यह मंगलाचरण लक्ष्य को खोजने के लिए संकलक उत्पन्न अभिव्यक्ति पेड़ को रोजगार:

public static MethodInfo MethodOf(Expression<System.Action> expression) 
{ 
    MethodCallExpression body = (MethodCallExpression)expression.Body; 
    return body.Method; 
} 

आप इसे इस तरह उपयोग कर सकते हैं, लेकिन यह भी किसी भी विधि के साथ इस्तेमाल किया जा सकता:

MethodInfo method = MethodOf(() => controller.Method3(default(int))); 
इसी के साथ

रास्ते से बाहर, हम एक सामान्य कार्यान्वयन का निर्माण कर सकते हैं:

public static bool MethodHasAuthorizeAttribute(Expression<System.Action> expression) 
{ 
    var method = MethodOf(expression); 

    const bool includeInherited = false; 
    return method.GetCustomAttributes(typeof(AuthorizeAttribute), includeInherited).Any(); 
} 

ठीक है, विधियों के लिए यह है। अब, यदि आप कक्षाओं या फ़ील्ड पर विशेषता चेक लागू करना चाहते हैं (मैं गुणों को छोड़ दूंगा क्योंकि वे वास्तव में विधियां हैं), हमें MemberInfo पर हमारी जांच करने की आवश्यकता है, जो Type, FieldInfo और MethodInfo के लिए विरासत रूट है। एक अलग विधि में गुण खोज निकालने और अच्छा नाम के साथ उचित एडाप्टर तरीकों प्रदान करने के रूप यह उतना आसान:

public static bool MethodHasAuthorizeAttribute(Expression<System.Action> expression) 
{ 
    MemberInfo member = MethodOf(expression); 
    return MemberHasAuthorizeAttribute(member); 
} 

public static bool TypeHasAuthorizeAttribute(Type t) 
{ 
    return MemberHasAuthorizeAttribute(t); 
} 

private static bool MemberHasAuthorizeAttribute(MemberInfo member) 
{ 
    const bool includeInherited = false; 
    return member.GetCustomAttributes(typeof(AuthorizeAttribute), includeInherited).Any(); 
} 

मैं एक व्यायाम के रूप क्षेत्रों के लिए कार्यान्वयन छोड़ देंगे, तो आप MethodOf रूप में एक ही चाल को रोजगार कर सकते हैं।

+0

ओपी कक्षाएं भी चाहता है। – Tigran

+0

अब मैं MethodHasAuthorizeAttribute (() => नियंत्रक निष्पादित कर सकता हूं। AJAXDashboardNodes (डिफ़ॉल्ट (TreeViewItem)) मुझे लगता है कि मैं उन अतिरिक्त वर्णों के साथ रह सकता हूं :) – 4rchie

+0

मैंने इस प्रतिक्रिया से एक नया प्रश्न बनाया है, पूछना कि कैसे सामान्यीकृत करना है समाधान: http://stackoverflow.com/questions/41493289/how-to-assert-that-a-method-has-a- निर्दिष्ट- योगदान –

0

कुछ नमूना खोजें जहां मुझे उस श्रेणी में विधियां मिलती हैं जिनमें निर्दिष्ट विशेषता है।

private static void GetMethodInfo(object className) 
     { 
      var methods = className.GetType().GetMethods(BindingFlags.Instance | BindingFlags.Public); 

      foreach(var m in methods) 
      { 
       var parameters = m.GetParameters(); 
       var att = m.GetCustomAttributes(typeof (CustomAttribute), true); 
      } 
     } 

पारित पैरामीटर एक वर्ग का एक उदाहरण है। आप अपनी आवश्यकता के अनुसार कोड को संशोधित कर सकते हैं जो बहुत आसान होना चाहिए।

1

मैं ऐसा ही कुछ कार्य करें: यह

Func<string,System.Web.Mvc.ActionResult> func = controller.Login; 
bool atrAuthorize = func.MethodHasAuthorizeAttribute(String.Empty); 
4

वहाँ वर्तमान नेट/सी # संस्करण के साथ ऊपर दूसरों की तुलना में एक आसान समाधान availabe है इस प्रकार है कॉलिंग

public static bool MethodHasAuthorizeAttribute(this Delegate pMethod, string pRoleAccess) 
{ 
    var mi = pMethod.GetMethodInfo(); 
    const bool includeInherited = false; 
    var atr = mi.GetCustomAttributes(typeof(AuthorizeAttribute), includeInherited) 
       .Select(t => (AuthorizeAttribute)t) 
       .Where(t => pRoleAccess.Length>0?t.Roles == pRoleAccess:true); 
    if (pRoleAccess == String.Empty) 
    { 
     return !atr.Any(); 
    } 
    else 
    { 
     return atr.Any(); 
    } 
} 

public static bool MethodHasAllowAnonymousAttribute(this Delegate pMethod) 
{ 
    var mi = pMethod.GetMethodInfo(); 
    const bool includeInherited = false; 
    var atr = mi.GetCustomAttributes(typeof(AllowAnonymousAttribute), includeInherited); 
    return atr.Any(); 
} 

(4.6.1 , सी # 6):

var method = typeof(TestClass).GetMethods() 
    .SingleOrDefault(x => x.Name == nameof(TestClass.TestMethod)); 

var attribute = method?.GetCustomAttributes(typeof(MethodAttribute), true) 
    .Single() as MethodAttribute; 
:

आप केवल एक एक विधि है कि नाम के साथ है, तो

bool isDefined = attribute != null; 

और तुम विशेषता के गुणों का उपयोग करना चाहते हैं, आपको लगता है कि के रूप में इस आसान कर सकते हैं::

var someInfo = attribute.SomeMethodInfo 

यदि आप विशेषता विधि पर सेट है

अब जाँच करने के लिए यदि एक ही नाम के साथ कई विधियां हैं, तो आप method.GetParameters() पर जा सकते हैं और .GetMethods().Single...

के बजाय पैरामीटर की जांच कर सकते हैं यदि आपको पता है कि आपकी विधि में कोई पैरामीटर नहीं है, इस चेक आसान है:

var method = typeof(TestClass).GetMethods() 
    .SingleOrDefault(
     x => x.Name == nameof(TestClass.TestMethod) 
     && x.GetParameters().Length == 0 
); 

यदि नहीं, तो इस और अधिक जटिल होने के लिए (पैरामीटर की जाँच, आदि) जा रहा है और अन्य समाधान रास्ता आसान है और उपयोग करने के लिए मजबूत कर रहे हैं।

तो: यदि आपके पास किसी विधि के लिए ओवरलोड नहीं है, या केवल निर्दिष्ट पैरामीटर के साथ किसी विधि से विशेषताओं को पढ़ना चाहते हैं तो इसका उपयोग करें। अन्यथा, MethodOf का उपयोग यहां अन्य उत्तरों द्वारा प्रदान किया गया है।

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