2013-01-13 28 views
17

संभव डुप्लिकेट:
C# wrap method via attributesबेसिक कार्यान्वयन मानक .नेट फ्रेमवर्क का उपयोग कर

मैं ऐसी कार्यक्षमता को प्राप्त करना चाहते हैं:

[Atomic] 
public void Foo() 
{   
    /* foo logic */ 
} 

कहाँ [Atomic] विशेषता एक विशेषता है, जो लेनदेन के दायरे में फ़ंक्शन तर्क को लपेटती है:

using(var scope = new TransactionScope()) 
{ 
    /* foo logic */ 
    scope.Complete(); 
} 

ऐसी विशेषता कैसे लिखें?

मैंने मूल रूप से वही question से पहले पूछा है, मुझे पता है कि यह एओपी का उपयोग करके किया जा सकता है, लेकिन मैंने उल्लेख नहीं किया कि मैं अवधारणा कार्यान्वयन या उपयोगी लेखों के कुछ सरल प्रमाणों की खोज कर रहा हूं जो मुझे यह लिखने में मदद कर सकते हैं शुद्ध .NET Framework का उपयोग करके (मुझे लगता है कि RealProxy और MarshalByRefObject प्रकारों का उपयोग करना, जिसके बारे में मैंने ब्राउज़िंग संबंधी प्रश्न पढ़े हैं)।

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

+0

यदि आप अपनी शिक्षा के लिए ऐसा कर रहे हैं, तो यह ठीक है, लेकिन यदि आप व्यवसाय की आवश्यकता को हल करने के लिए ऐसा कर रहे हैं, तो यह आपके लिए पहले से ही डब्ल्यूसीएफ और कॉम + में किया जा चुका है। –

उत्तर

20

यह एक बुनियादी बात की तरह लगता है ...

यह (कई) चीजें हैं जो अवधारणा को समझने के लिए सरल कर रहे हैं में से एक है, लेकिन बिल्कुल नहीं आसान लागू करने के लिए।

Oded's answer के अनुसार, .NET में गुण कुछ भी नहीं करते हैं। वे केवल अस्तित्व में हैं ताकि अन्य कोड (या डेवलपर्स) बाद में उन्हें देख सकें। एक फैंसी टिप्पणी के रूप में इसके बारे में सोचो।

इसी के साथ

मन में, तो आप इस

public class AtomicAttribute : Attribute { } 

अब कठिन हिस्सा की तरह अपने गुण लिख सकते हैं, तो आप उस विशेषता के लिए स्कैन करने के लिए कुछ कोड लिखते हैं, और कोड के व्यवहार बदलना होगा।

को देखते हुए सी # एक संकलित भाषा है, और .NET CLR के नियमों को देखते हुए है कि वहाँ सैद्धांतिक रूप से कर रहे हैं सी # संकलक में इस

  1. हुक करने के लिए 3 तरीके, और आउटपुट अलग कोड जब यह बना उस विशेषता को देखता है।
    ऐसा लगता है कि यह अच्छा होगा, लेकिन यह अभी संभव नहीं है । शायद Roslyn प्रोजेक्ट भविष्य में इसकी अनुमति दे सकता है, लेकिन अभी के लिए, आप इसे नहीं कर सकते हैं।

  2. के बाद .NET असेंबली स्कैन करने वाला कुछ लिखें C# कंपाइलर ने इसे MSIL में परिवर्तित कर दिया है, और MSIL को बदल दिया है।
    यह मूल रूप से PostSharp करता है। स्कैनिंग और पुनर्लेखन एमएसआईएल हार्ड है। Mono.Cecil जैसे पुस्तकालय हैं जो मदद कर सकते हैं, लेकिन यह अभी भी एक बेहद मुश्किल समस्या है। यह डीबगर, आदि में भी हस्तक्षेप कर सकता है।

  3. प्रोग्राम चलाने पर प्रोग्राम की निगरानी करने के लिए .NET प्रोफाइलिंग API का उपयोग करें, और हर बार जब आप उस विशेषता के साथ फ़ंक्शन कॉल देखते हैं, तो उसे किसी अन्य रैपर फ़ंक्शन पर रीडायरेक्ट करें।
    यह शायद सबसे आसान विकल्प है (हालांकि यह अभी भी बहुत कठिन) है, लेकिन दोष यह है कि अब आपका प्रोग्राम प्रोफाइलर के तहत चलाया जाना चाहिए। यह आपके विकास पीसी पर ठीक हो सकता है, लेकिन यदि आप इसे तैनात करने का प्रयास करते हैं तो इससे बड़ी समस्या होगी। इसके अलावा, इस दृष्टिकोण का उपयोग करके एक बड़ा प्रदर्शन हिट होने की संभावना है।

मेरी राय में, अपने सबसे अच्छे शर्त एक आवरण समारोह जो लेनदेन सेट बनाने के लिए, और फिर इसे एक लैम्ब्डा जो वास्तविक काम करता है पारित करने के लिए है। इस तरह:

public static class Ext 
{ 
    public static void Atomic(Action action) 
    { 
     using(var scope = new TransactionScope()) 
     { 
      action(); 
      scope.Commit(); 
     } 
    } 
} 

..... 

using static Ext; // as of VS2015 

public void Foo() 
{ 
    Atomic(() => { 
     // foo logic 
    } 
} 

इस के लिए फैंसी कंप्यूटर विज्ञान अवधि Higher order programming

+0

आपके समय के लिए धन्यवाद। मैं अब यह प्राप्त करना शुरू कर रहा हूं कि वास्तव में मैंने वास्तव में क्या पूछा है। सादर। – jwaliszko

+0

यह बिल्कुल सही नहीं है कि गुण कुछ भी नहीं करते हैं। System.Web.Http.AuthorizeAttribute को देखें जो अनुरोध के आईपीआर प्रिंसिपल के प्रमाणीकरण को संभालता है। – Polymorphix

+2

@ पॉलिमॉर्फिक्स नोप, System.Web.Http.AuthorizeAttribute भी कुछ भी नहीं करता है। जब एएसपी.नेट वेब एपीआई इसकी ढीली चीजें कर रही है और अपनी कक्षाओं के उदाहरण बना रही है, तो यह AuthorizeAttribute की तलाश में है, और इसे देखकर अलग-अलग कार्य करती है, लेकिन विशेषता स्वयं बस किसी के लिए इसे देखने के लिए प्रतीक्षा करती है –

10

विशेषताएँ मेटा डेटा हैं - सभी वे हैं।

ऐसे कई मेटाडेटा का लाभ उठा सकते हैं, लेकिन इस तरह के टूलिंग को विशेषता के बारे में पता होना चाहिए।

पोस्टशर्प जैसे एओपी टूल्स कोड में पहलुओं को बुनाई के बारे में जानने के लिए इस तरह के मेटाडेटा को पढ़ते हैं।

संक्षेप में - सिर्फ एक AtomicAttribute लेखन आप कुछ भी नहीं दे देंगे - आप AOP प्राप्त करने के लिए यह करने के लिए एक उपकरण है कि इस विशेषता के बारे में जानता है के माध्यम से संकलित विधानसभा गुजरती हैं और "कुछ" करने की आवश्यकता होगी।

3

यह बिल्कुल मूल बात नहीं है। कोई अतिरिक्त कोड चलाया नहीं जाता है क्योंकि किसी विधि में एक विशेषता होती है, इसलिए TransactionScope कोड डालने के लिए कहीं भी नहीं है।

आपको अपनी असेंबली में प्रत्येक वर्ग पर हर विधि पर पुनरावृत्ति करने के लिए एप्लिकेशन स्टार्ट-अप उपयोग प्रतिबिंब पर और AtomicAttribute के साथ चिह्नित विधियों को खोजने के लिए क्या करना होगा, फिर उस ऑब्जेक्ट के चारों ओर एक कस्टम प्रॉक्सी लिखें। फिर किसी भी तरह से वास्तविक कार्यान्वयन के बजाय अपनी प्रॉक्सी को कॉल करने के लिए सब कुछ प्राप्त करें, शायद एक निर्भरता इंजेक्शन ढांचे का उपयोग कर।

अधिकांश एओपी ढांचे इसे समय पर करते हैं। उदाहरण के लिए PostSharp VisualStudio आपकी असेंबली बनाता है के बाद चलता है। यह आपकी असेंबली को स्कैन करता है और प्रॉक्सी और एओपी इंटरसेप्टर को शामिल करने के लिए आईएल कोड को फिर से लिखता है। इस तरह विधानसभा पूरी तरह से चलने के लिए तैयार है, लेकिन आईएल ने जो मूल रूप से लिखा है उससे बदल गया है।

+0

मैं फ्रेमवर्क के बारे में अपनी धारणा को विस्तारित करने के लिए कुछ विवरणों के साथ इस क्षेत्र में जाना चाहता हूं और दूसरे पैराग्राफ में आपके द्वारा वर्णित कुछ मूलभूत सामग्री करता हूं। उत्तर के लिए धन्यवाद। – jwaliszko

2

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

तो आप ऐसा करते हैं जब:

var something = IoC.Resolve<ISomething>(); 

something आपत्ति नहीं है, जो आपने कार्यान्वित लेकिन प्रॉक्सी है। उस प्रॉक्सी में आप विधि कॉल के पहले और बाद में जो भी चाहें कर सकते हैं।