c# - सी#में एक साधारण गतिशील प्रॉक्सी कैसे बनाएं




.net reflection (5)

मैं किसी ऑब्जेक्ट को कुछ कार्यक्षमता जोड़ने के लिए गतिशील प्रॉक्सी ऑब्जेक्ट बनाना चाहता हूं।

मूल रूप से मैं एक ऑब्जेक्ट प्राप्त करना चाहता हूं, इसे उस ऑब्जेक्ट से लपेटो जो मूल के समान दिखता है, और सभी कॉलों को रोकता है।

class Wrapper : DynamicProxy// dynamic proxy is not a reall class, but i guess something like this exists...
{
    public static T Wrap(T obj)
    {
        return (T) new Wrapper(obj);
    }

    public override object InterceptCall(MethodInfo info, object[] args)
    {
        // do stuff
    }

}

बस स्पष्ट करने के लिए, मैं डब्ल्यूसीएफ चैनल फैक्ट्री के समान कुछ करना चाहता हूं ...

मैं एक बक्षीस जोड़ रहा हूं, क्योंकि मुझे प्रॉक्सी कक्षाओं (इंटरफेस नहीं) और गैर वर्चुअल विधियों को संभालने के लिए एक अच्छा तरीका चाहिए (जैसे कि मैंने विरासत में और "नए" कीवर्ड के तहत मेथॉन्ड जोड़ा है)। मुझे यकीन है कि यह सब बहुत संभव है क्योंकि नेट करता है।


आप इसे DynamicObject और DynamicObject संयोजन के साथ कर सकते हैं लेकिन आपको एक इंटरफ़ेस रखना होगा जो उन कार्यों और गुणों को लागू करता है जिन्हें आप प्रॉक्सी करना चाहते हैं।

public interface IDoStuff
{
    void Foo();
}

public class Wrapper<T> : DynamicObject
{
    private readonly T _wrappedObject;

    public static T1 Wrap<T1>(T obj) where T1 : class
    {
        if (!typeof(T1).IsInterface)
            throw new ArgumentException("T1 must be an Interface");

        return new Wrapper<T>(obj).ActLike<T1>();
    }

    //you can make the contructor private so you are forced to use the Wrap method.
    private Wrapper(T obj)
    {
        _wrappedObject = obj;
    }

    public override bool TryInvokeMember(InvokeMemberBinder binder, object[] args, out object result)
    {
        try
        {
            //do stuff here

            //call _wrappedObject object
            result = _wrappedObject.GetType().GetMethod(binder.Name).Invoke(_wrappedObject, args);
            return true;
        }
        catch
        {
            result = null;
            return false;
        }
    }
}

आप निश्चित रूप से टाइप-सुरक्षा खोने का विकल्प चुन सकते हैं और एक डायनामिक ऑब्जेक्ट के साथ जा सकते हैं जैसे मैंने दिखाया और फिर बतख-कास्टिंग छोड़ दिया।

मैंने इस ऑब्जेक्ट प्रॉक्सी का एक पारदर्शी विस्तारित संस्करण बनाया है, और इसे here खोल दिया here


एक और विकल्प ContextBoundObject

विधि कॉल का पता लगाने के लिए इस दृष्टिकोण का उपयोग करके 8-9 साल पहले कोडप्रोजेक्ट पर एक लेख था।


मुझे इसे जल्द ही लिखा होगा, लेकिन कभी भी ध्यान न दें।

मेरे मुद्दे में एक विशेष "गॉचाचा" था जिसे मुझे कक्षाओं को प्रॉक्सी करने में सक्षम होना था और इंटरफेस नहीं।

इसके लिए दो समाधान हैं:

  1. असली प्रॉक्सी और दोस्तों, मूल रूप से नेट रीमोटिंग का उपयोग करना है। ContextBoundObject से प्राप्त करने के लिए एक की आवश्यकता है।

  2. System.Reflection.Emit का उपयोग कर प्रॉक्सी बनाना। spring द्वारा किए गए अनुसार आप अपने ProxyFactoryObject के कोड को भी देख सकते हैं। इस subject पर another तीन articles यहां दिए गए हैं।

वैसे, दूसरे दृष्टिकोण में काफी सीमा है, आप गैर आभासी तरीकों को प्रॉक्सी नहीं कर सकते हैं।



PostSharp पर एक नज़र डालें। मैं वेनिला में जो कुछ भी करना चाहता हूं उसे करने के तरीके के बारे में नहीं जानता। नेट, लेकिन पोस्टशर्प "ऑनमेथिंग बाउंडरीएस्पेक्ट" जैसी चीजें प्रदान करता है जिसका उपयोग विधि के अंदर कोड को प्रतिस्थापित या लपेटने के लिए किया जा सकता है।

मैंने इसे लॉगिंग, पैरामीटर सत्यापन, अपवाद हैंडलिंग इत्यादि जैसी चीजों को करने के लिए उपयोग किया है।

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





aop