2011-08-23 8 views
8

मेरे आवेदन में मैंने पहले एक विधि को "एनोटेट" करने के लिए नियमित सी # विशेषताओं का उपयोग किया था। उदा .:एक विधि पर एकाधिक पहलू

 

[Foo(SomeKey="A", SomeValue="3")] 
[Foo(SomeKey="B", SomeValue="4")] 
public void TheMethod() 
{ 
    SpecialAttributeLogicHere(); 
} 

 

क्या SpecialAttributeLogicHere() किया था, संजीदगी से सभी फू-गुण इस विशेष विधि एनोटेट कि को देखने के लिए किया गया था। यह तब (अपने आप पर), सभी चाबियों और मूल्यों के लिए अपना स्वयं का शब्दकोश बनायेगा।

अब मैं पोस्टशर्प में जाने की कोशिश कर रहा हूं, क्योंकि विशेष एट्रिब्यूट लॉजिक को एक पहलू में रखा जा सकता है (और विधि निकाय से हटाया गया है जो बहुत साफ है!), ऑनएन्ट्री के भीतर। Foo को एक पहलू से प्रतिस्थापित किया जाएगा जो OnMethodBoundaryAspect को बढ़ाता है।

मैं अभी भी यह निम्नलिखित तरीके से उपयोग करना चाहते हैं:


[Foo(SomeKey="A", SomeValue="3")] 
[Foo(SomeKey="B", SomeValue="4")] 

लेकिन अगर फू एक OnEntry, है इसका मतलब है कि "SpecialAttributeLogic" दो बार निष्पादित किया जाएगा। मुझे मूल रूप से प्रत्येक Foo() से सभी कुंजी और मानों को एक शब्दकोश में "इकट्ठा" करने की आवश्यकता होती है, जिसे मैं कुछ तर्क लागू करता हूं।

पोस्टशर्प के साथ यह (या सर्वोत्तम प्रथाओं) कैसे करें? धन्यवाद!

+0

नीचे दिए गए मेरे उत्तर में काम करने का उदाहरण जोड़ा गया। –

उत्तर

2

ऐसा लगता है कि आप अपनी विधि के अंदर नाम नामकरण करना चाहते हैं। आप इसे एक पहलू से नहीं कर सकते हैं। मेरा सुझाव है कि आप एक विधिInterceptionAspect का उपयोग करते हैं और विधि पर विशेषताओं को प्रतिबिंबित करते हैं और फिर अपना संग्रह बनाते हैं और इसे पैरामीटर के माध्यम से विधि में पास करते हैं (शायद एक अधिभारित विधि का उपयोग कर) या इसे क्लास सदस्य के रूप में सेट करना।

प्रदर्शन को इष्टतम रखने के लिए आप संकलन समय पर मानों को प्रतिबिंबित कर सकते हैं।

यहां आपकी समस्या का एक त्वरित समाधान है। यह थोड़ा बदसूरत है (आपको फिट करने के लिए संशोधन करने की आवश्यकता होगी)। अन्य तरीके हैं लेकिन वे "जेनेरिक" नहीं हैं।

namespace ConsoleApplication12 
{ 
    class Program 
    { 
     static void Main(string[] args) 
     { 
      MyExampleClass ec = new MyExampleClass(); 
      ec.MyMethod(); 
     } 
    } 

    public class MyExampleClass 
    { 
     [Special(Key = "test1", Value = "1234")] 
     [Special(Key = "test2", Value = "4567")] 
     [MyAspect] 
     public void MyMethod() 
     { 
      MyMethod(new Dictionary<string, string>()); 
     } 

     public void MyMethod(Dictionary<string, string> values) 
     { 
      //Do work 
     } 

    } 

    [Serializable] 
    public class MyAspect : MethodInterceptionAspect 
    { 
     Dictionary<string, string> values = new Dictionary<string, string>(); 
     MethodInfo target; 

     public override void CompileTimeInitialize(System.Reflection.MethodBase method, AspectInfo aspectInfo) 
     { 
      target = method.DeclaringType.GetMethod(method.Name, new Type[] { typeof(Dictionary<string, string>) }); 

      foreach (Attribute a in method.GetCustomAttributes(false)) 
      { 
       if (a is SpecialAttribute) 
       { 
        values.Add(((SpecialAttribute)a).Key, ((SpecialAttribute)a).Value); 
       } 
      } 
     } 

     public override void OnInvoke(MethodInterceptionArgs args) 
     { 
      if (values == null || values.Count < 1) 
      { 
       args.Proceed(); 
      } 
      else 
      { 
       target.Invoke(args.Instance, new object[] { values }); 
      } 

     } 
    } 
    [AttributeUsage(AttributeTargets.Method, AllowMultiple = true) ] 
    public class SpecialAttribute : Attribute 
    { 
     public string Key { get; set; } 
     public string Value { get; set; } 
    } 
} 

लक्ष्य और मूल्य दोनों रनटाइम पर खपत के लिए संकलन (रनटाइम नहीं) पर प्रारंभ किए गए हैं। वे संकलन के पहलू के साथ serialized मिलता है। इस तरह आप रनटाइम पर प्रतिबिंब हिट पर सहेजते हैं।

+0

अच्छा जवाब। वैकल्पिक रूप से मुझे लगता है कि मैं वही दृष्टिकोण कर सकता हूं, लेकिन MethodInterceptionAspect के बजाय OnMethodBoundaryAspect का उपयोग कर रहा हूं। फिर, ऑनएन्ट्री में मैं प्रतिबिंब का उपयोग कर विधि के गुणों को पढ़ूंगा। लेकिन दूसरी ओर, शायद मेरी जरूरतों के लिए MethodInterceptionApect बेहतर है। मुझे इसे कुछ विचार देना होगा ... –

+1

हाँ आप ऐसा कर सकते हैं, लेकिन जब आप इसे गुणों से जोड़ते हैं तो समस्या डेटा तक पहुंच प्राप्त कर रही है। मैं विशेषता को एक पहलू नहीं बनाऊंगा क्योंकि आप अपने कोड को निष्पादित करने और वास्तव में जटिल करने के कई पहलुओं को समाप्त कर देंगे। लेकिन MethodBoundaryAspect का उपयोग विधि विधि अधिभार की आवश्यकता को रोकता है। तो किसी भी तरह से ठीक होना चाहिए। –

0

बस एक नोट के रूप में, मैंने MethodInterceptionAspect का उपयोग करके समाप्त किया और केवल OnInvoke को ओवरराइड किया। OnInvoke के भीतर मैंने args.Method.GetCustomAttributes() को देखा, मुझे सभी सिस्टम दे रहे हैं। मेरे द्वारा सेट की गई विशेषताएं (यानी DustinDavis 'उदाहरण में SpecialAttribute)।

उन विशेषताओं और उनकी गुणों का उपयोग करके, मैं तर्क चलाने के लिए आवश्यक तर्क चला सकता हूं। यदि तर्क सफल होता है, तो मैं तर्क के साथ समाप्त होता हूं। आगे बढ़ें(), अगर नहीं, तो मैं अपवाद फेंकता हूं।

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