2010-08-16 21 views
7

में इंटरफ़ेस को कार्यान्वित करें, मैं यह परीक्षण पास करना चाहता हूं - किसी को भी यह पता चल जाएगा कि यह कैसे करें?ऑब्जेक्ट को गतिशील रूप से कोड

public class Something 
{ 
    public string Name {get; set} 
} 

public interface IWithId 
{ 
    public Guid Id {get; set} 
} 

public class IdExtender 
{ 
    public static Object Extend(object toExtend) 
    { 
     ...? 
    } 
} 

public class Tests 
{ 
    [Test] 
    public void Should_extend_any_object() 
    { 
     var thing = new Something { Name = "Hello World!"}; 
     var extended = IdExtender.Extend(thing); 
     Assert.IsTrue(extended is IWithId); 
     Assert.IsTrue(extended.Id is Guid); 
     Assert.IsTrue(extened.Name == "Hello World!"); 
    } 
} 

मैं कुछ इस तरह लगता है कि महल गतिशील प्रॉक्सी, linfu, आदि ... लेकिन कैसे के साथ किया जा सकता है?

+0

यदि ऐसा करने का कोई तरीका है, तो मैं उत्सुक हूं .. –

+0

मैं सवाल का जवाब दे सकता हूं, मैंने इसे पहले किया है, लेकिन मैं कुछ एकल-लाइनर और एक संदर्भ या दो से ट्रिम नहीं करना चाहता प्रलेखन के लिए यदि मैं खुले दृश्य स्टूडियो को क्रैक करने और समाधान को एक साथ रखने की परेशानी से गुज़रने जा रहा हूं ... तो मैं थोड़ा इंतजार करूंगा, और अगर कुछ घंटों में कोई अच्छा जवाब नहीं है, तो मैं एक जमा करूंगा जवाब। – Steve

+0

क्या यह उदाहरण या पूरे कुछ प्रकार का विस्तार करेगा? –

उत्तर

3

कैसल डी पी (जाहिर है)

खैर का उपयोग करना - आप के बाद से आप एक मौजूदा प्रकार एक नए इंटरफ़ेस हासिल रूप में अपने कार्यक्रम निष्पादित हो रहा है नहीं हो सकता है वापस जाने के लिए एक नई वस्तु बनाने करना होगा।

ऐसा करने के लिए आपको प्रॉक्सी बनाने की आवश्यकता होगी और फिर प्रॉक्सी पर अपनी पूर्व-मौजूदा ऑब्जेक्ट की स्थिति दोहराएं। डीपी ओओटीबी नहीं करता है। V2.5 में आप लक्ष्य के साथ नई कक्षा प्रॉक्सी का उपयोग कर सकते हैं, लेकिन यह केवल तभी काम करेगा जब प्रकार के सभी गुण वर्चुअल थे।

वैसे भी। आप नए प्रकार को IWithId इंटरफ़ेस प्राप्त कर सकते हैं या तो संपत्ति को कार्यान्वित करने वाली मौजूदा ऑब्जेक्ट के साथ प्रॉक्सी में मिलाकर। फिर इंटरफ़ेस के सदस्यों को कॉल ऑब्जेक्ट पर अग्रेषित की जाएगी।

वैकल्पिक रूप से आप इसे लागू करने के लिए अतिरिक्त इंटरफ़ेस प्रदान कर सकते हैं और एक इंटरसेप्टर को कार्यान्वयनकर्ता की भूमिका में भर सकते हैं।

+0

दिलचस्प लगता है - आपके पास कहीं कोड नमूना नहीं है? – Jan

+0

मैं एक उत्पादन कर सकता है ... मुझे लगता है कि –

+0

स्वीकार आप इसे लगा बाहर मतलब है, और मुझे आप के लिए एक नमूना बनाने के लिए नहीं करना चाहते? –

1

mocking framework like Moq या RhinoMocks का उपयोग क्यों न करें। वे आपको सीधे प्रॉक्सी बनाने के बिना इंटरफेस को गतिशील रूप से कार्यान्वित करने की अनुमति देते हैं।

Moq के साथ आप लिख सकते हैं:

var mock = new Mock<IWithId>(); // mock the interface 
mock.Setup(foo => foo.Name).Returns("Hello World"); // setup a property 

कि के अलावा, आप कुछ जटिल काम करने के लिए आप क्या चाहते हैं पाने के लिए होगा। जहां तक ​​मुझे पता है, आप रनटाइम पर मौजूदा क्लास में विधि या गुण जोड़ नहीं सकते हैं। आप एक नई वस्तु का एक उदाहरण वापस कर सकते हैं जो गतिशील रूप से पारित प्रकार से प्राप्त होता है। कैसल निश्चित रूप से इसकी अनुमति देता है, लेकिन आवश्यक कोड विशेष रूप से सुरुचिपूर्ण या सरल नहीं है।

+1

एचएम , लेकिन क्या वे इसे किसी मौजूदा ऑब्जेक्ट में जोड़ सकते हैं? यह एक दिलचस्प दुर्व्यवहार होगा :) – Jan

+0

I @ illdev: Moq के साथ इसे किसी मौजूदा ऑब्जेक्ट में जोड़ना आवश्यक नहीं होगा - आप केवल दी गई संपत्ति रखने के लिए नकली स्थापित करेंगे। आप किसी भी मौजूदा वर्ग में विधियों या गुणों को गतिशील रूप से जोड़ नहीं सकते हैं। आप शायद .NET 4.0 डायनामिक ऑब्जेक्ट्स का उपयोग कर सकते हैं, लेकिन कॉलर को 'गतिशील' का उपयोग करने की आवश्यकता होगी। – LBushkin

+0

पोस्टर ने अनुमान नहीं लगाया कि उसके प्रकार को गतिशील रूप से बदलना पड़ा। उसकी "कनवर्टर" विधि का रिटर्न प्रकार "ऑब्जेक्ट" है। यह निश्चित रूप से .NET 3.5 और निम्न – Steve

0

किसी संपत्ति या इंटरफ़ेस को गतिशील रूप से संलग्न करने के सवाल को अलग करना, ऐसा लगता है कि आप जो कुछ करने का प्रयास कर रहे हैं वह अतिरिक्त डेटा के साथ मौजूदा कक्षाओं को बढ़ा रहा है। इस समस्या का एक बहुत ही सामान्य समाधान Dictionary<Something, SomethingExtra> का उपयोग करना है और इसे मैपिंग को बनाए रखने वाले कुछ सेवा वर्ग में संग्रहीत करना है। अब, जब आपको SomethingExtra तक पहुंच की आवश्यकता है, तो आप संबंधित जानकारी के लिए सेवा कक्षा से पूछें।

लाभ:

  1. कार्यान्वयन को समझते हैं और एक समाधान प्रतिबिंब और गतिशील प्रॉक्सी पीढ़ी का उपयोग करने से बनाए रखने के लिए आसान है।

  2. यदि आपको विस्तारित प्रकार से प्राप्त करने की आवश्यकता है, तो वर्ग को सील नहीं किया जा सकता है। एसोसिएटिंग जानकारी बाहरी रूप से मुहरबंद कक्षाओं के साथ ठीक काम करती है।

  3. आप बढ़ी हुई वस्तु के निर्माण के लिए ज़िम्मेदार होने के बिना जानकारी को जोड़ सकते हैं। आप कहीं भी बनाए गए उदाहरण ले सकते हैं और नई जानकारी को जोड़ सकते हैं।

नुकसान:

  1. आप सेवा उदाहरण है कि मानचित्रण का कहना है इंजेक्षन की जरूरत है। यदि आप सिंगलटन स्थिर एक्सेसर के माध्यम से एक, मैनुअल इंजेक्शन (आमतौर पर एक कन्स्ट्रक्टर के माध्यम से पारित) का उपयोग कर रहे हैं, या यदि कोई अन्य विकल्प नहीं है, तो आप इसे आईओसी फ्रेमवर्क के माध्यम से कर सकते हैं।

  2. यदि आपके पास बहुत बड़ी संख्या है और उन्हें तेजी से बनाया/हटाया जा रहा है, तो शब्दकोश ओवरहेड ध्यान देने योग्य हो सकता है। मुझे संदेह है कि उपरोक्त कार्यान्वयन की तुलना में ओवरहेड ध्यान देने योग्य होने से पहले आपको बहुत भारी भार की आवश्यकता होगी।

+0

अप्रबंधित दुनिया में आपका स्वागत है। डेवलपर को यह सुनिश्चित करना होगा कि उन्होंने शब्दकोश के साथ किसी भी ऑब्जेक्ट प्रविष्टियों को हटा दिया होगा - अनिवार्य रूप से, ऑब्जेक्ट को जारी करने के लिए (कचरा संग्रह के लिए इसे मुक्त करें)। – Steve

+0

@ स्टेव, अच्छा बिंदु, जो नुकसान सूची पर जाना चाहिए। यह मूल रूप से तरीका है कि संलग्न निर्भरता गुण WPF में काम करते हैं, इसलिए मुझे यह देखने के लिए कुछ जांच करनी होगी कि एमएस इस समस्या को कैसे हल करता है। –

+0

@Steve, मैं कैसे एमएस समस्या का हल पर कोई जानकारी नहीं मिल सकता है, लेकिन यह कमजोर संदर्भों का उपयोग और समय समय पर उदाहरणों कि एकत्र किया गया है करने के लिए अभिलेखों का शब्दकोश शुद्धिकरण सुलझाया जा सकता है। दिलचस्प बात यह है कि यह पहली बार है जब मुझे कमजोर संदर्भों के लिए एक अच्छा उपयोग केस मिला है। –

3

अभी के लिए मैं इस तरह linfu साथ जा रहा हूँ:

public class IdExtender 
{ 
    public static Object Extend(object toExtend) 
    { 
     var dyn = new DynamicObject(toExtend); 
     dyn.MixWith(new WithId { 
           Id = Guid.New() 
           }); 
     var extended = dyn.CreateDuck<IWithId>(returnValue.GetType().GetInterfaces()); 
     return extended; 
    } 
} 
+0

यह इतना अच्छा हो सकता है कि स्तर हो! – Jan

+0

गूगल पर मिला - DynamicObject instantiated जा सिर्फ –

1

मैं वास्तव में एक similar question पिछले सप्ताह जवाब दे दिया है। मैंने एक छोटी सी लाइब्रेरी भी लिखी है जो यह एक काम करता है। यह मेरे blog से उपलब्ध है, जिसे मैं लापरवाही से जोड़ रहा हूं।

कैसल डायनैमिक प्रॉक्सी का उपयोग करके आप लगभग प्राप्त करने योग्य हैं। एकमात्र बाधा यह है कि मौजूदा उदाहरण एक इंटरफ़ेस को लागू करना चाहिए और उस इंटरफ़ेस के माध्यम से आपकी सभी संपत्तियों/विधियों में रुचि है।

public static TIntf CreateMixinWithTarget<TIntf>(TIntf target, params object[] instances) where TIntf : class{ 

    ProxyGenerator generator = new ProxyGenerator(); 
    ProxyGenerationOptions options = new ProxyGenerationOptions(); 

    instances.ToList().ForEach(obj => options.AddMixinInstance(obj)); 

    return generator.CreateInterfaceProxyWithTarget <TIntf>(target, options); 
} 

[Test] 
public void Should_extend_any_object() 
{ 
    var thing = new Something { Name = "Hello World!"}; 
    var extended = CreateMixinWithTarget<ISomething>(thing, new WithId(), new GuidImpl()); 
    Assert.IsTrue(extended is IWithId); 
    Assert.IsTrue(extended.Id is Guid); 
    Assert.IsTrue(extened.Name == "Hello World!"); 
} 
+0

मेरे लिए दुर्भाग्य है कि से प्राप्त नहीं कर सकते। मेरे मामले में उदाहरण किसी भी इंटरफेस को लागू नहीं करते हैं ... जब आप कह रहे हैं, कि उन्हें चाहिए - यह कैसे समझ में आता है? क्या यह लागू नहीं होता है कि इंटरफ़ेस भी लागू किया गया है? वैसे भी, अगर आप linfu संस्करण नीचे की तुलना करें - मुझे लगता है कि जिस तरह से और अधिक सुरुचिपूर्ण है .... – Jan

+0

यह गतिशील प्रॉक्सी प्रतिबंध नहीं है और जिस तरह से यह प्रॉक्सी बनाता है के साथ क्या करना है। एक ही तरीका है एक मौजूदा उदाहरण के आधार पर एक प्रॉक्सी बनाने के लिए CreateInterfaceProxyWithTarget कॉल करने के लिए है, लेकिन चेतावनी है कि उदाहरण के लिए एक इंटरफेस प्रकार परम द्वारा निर्दिष्ट को लागू करना चाहिए है। और मैं इस बात से सहमत है, linfu संस्करण अधिक स्वच्छ है। –

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