2009-11-03 13 views
5

मैं कैसे एक समस्या को हल करने में देख रहा हूँ और मैं भी यकीन है कि यह में बिल्कुल सी # & .NET 3.5 संभव हो सकता है नहीं कर रहा हूँ:सी # रनटाइम पर गतिशील रूप से विभिन्न इंटरफेस को लागू करने वाली ऑब्जेक्ट कैसे उत्पन्न करें?

मैं इंटरफेस के एक सीमित संख्या में हैं कहो, हर एक का वर्णन, विधियों के गैर-संबंधित सेट। अब मेरे पास एक वास्तविक वास्तविक डिवाइस हैं जो प्रत्येक इन इंटरफेस के बस एक सबसेट को कार्यान्वित कर सकता है।

इन उपकरणों के साथ कॉमर्स के सेट-अप के दौरान वे मुझे बताएंगे कि उनके पास कौन सी क्षमताएं हैं। मैं अब एक वस्तु इंटरफेस (डिवाइस से प्रत्येक जैसी एक क्षमता) को लागू करने बनाना चाहेंगे तो मेरे आवेदन वास्तुकला में उच्च ऊपर है कि मैं कर सकती हूं: ऊपर उल्लिखित इंटरफेस के खिलाफ

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

मुझे इस समस्या की ओर उपयोग करने के लिए सभी दृष्टिकोणों पर यकीन नहीं है। किसी भी टिप्पणी या दृष्टिकोण का स्वागत है!

+0

सबसे पहले, आपकी टिप्पणियों और सुझावों के लिए सभी को धन्यवाद। बहुत ज्यादा अधिमूल्यित! ठीक है, मुझे लगता है कि मुझे जिस समस्या का सामना करना पड़ रहा है उस पर मुझे थोड़ा और विस्तार करना चाहिए। मेरे पास क्षमताओं की एक निश्चित संख्या है, उदा। CanMakeCoffe, CanCleanKitchen, आदि कुछ क्षमताएं हैं जो अधिकांश डिवाइस लागू होंगी, उदा। CanMakeCoffee। मैं से बचने के लिए चाहते हैं क्या CDeviceOne में के रूप में इन डिवाइस के लिए स्रोत कोड की कक्षाओं में कहीं परिभाषित करने के लिए है: ICanMakeCoffee, ICanCleanKitchen CDeviceTwo: ICanMakeCoffee –

+0

मैं नहीं बल्कि डिवाइस मुझे बताओ, जब वे वे क्या कर सकते कनेक्ट होगा और फिर मैं एक वस्तु बनाउंगा जो उनकी क्षमताओं जैसा दिखता है। क्या इससे कोई समझ आती है? –

उत्तर

3

LinFu.DynamicObject जैसी कुछ कोशिश करें।

+0

वास्तव में बहुत दिलचस्प है। मैं विशेष रूप से एक मिश्रण बनाने के विचार पसंद है। मैं उत्पादन कोड के लिए उस तरह के ढांचे का उपयोग करने में थोड़ा संकोच कर रहा हूं ... मुझे लाइसेंस देखना होगा। वैसे भी इसके लिए धन्यवाद! –

+0

इसे एलजीपीएल के रूप में लाइसेंस प्राप्त है। और आपको फिलिप का शुक्रिया अदा करना चाहिए, मुझे नहीं :) –

5

उपयोग एक mocking framework ऐसे Moq के रूप में, RhinoMocks या TypeMock Isolator

आप कुछ निचले स्तर करने के लिए देख रहे हैं, Castle DynamicProxy तरह बातें आपके लिए एक अच्छा दिशा हो सकता है।

+2

बतख टाइपिंग की खोज भी परिणाम दे सकती है। – leppie

+0

@leppie: बहुत अच्छा बिंदु। @ टिमो: यदि आप आयरनपीथन या आयरन रूबी (या सी # 4 में गतिशील संबंधित सामग्री) जैसी गतिशील भाषा का उपयोग करते हैं, तो आप कुछ उपयोगी प्राप्त करने में सक्षम हो सकते हैं (हालांकि आप वास्तविक 'इंटरफ़ेस' परिभाषाओं का उपयोग नहीं करेंगे और 'is' या' कार्यान्वयन में –

+0

@leppie: आपके सुझाव के लिए धन्यवाद। मुझे पहले से ही बतख टाइपिंग पर एक नज़र थी लेकिन मुझे यकीन नहीं था कि यह समस्या के साथ मेरी मदद करेगा। मैं वैसे भी एक और नजर डालेगा! @ रूबेन: आपके पॉइंटर्स के लिए डायनामिकप्रॉक्सी के लिए धन्यवाद। सबसे दिलचस्प! मैं वहां एक नजदीकी नजर रखूंगा। –

0

यह संभव है, बस आसान नहीं है। आपको एक स्ट्रिंग बनाने की आवश्यकता है जो मूल रूप से एक स्रोत फ़ाइल है और उसके बाद CSharpCodeProvider बनाएं और उपयोग करें, जिसे आप अपने कोड को संकलित करने के लिए ऑर्डर करते हैं। यदि यह काम करता है, तो आप प्रतिबिंब के माध्यम से अपनी बनाई गई वस्तुओं को मैन्युअल रूप से एक्सेस कर सकते हैं।

रुचि के लिए, मैंने इसे थोड़ी देर पहले किया, विवरण थोड़ी धुंधली हैं।

+2

शायद आईएल कोड को स्मृति में गतिशील असेंबली में छोड़ना उतना ही आसान होगा। हालांकि, एक मॉकिंग फ्रेमवर्क यह आसान/कम कोड में कर सकता है। ;) – sisve

1

शायद आपको इसे "गतिशील" बनाने की आवश्यकता नहीं है।

क्या आपने Abstract Factory पैटर्न की जांच की है? ऐसा लगता है कि मूल रूप से आपको एक डिवाइस टाइप पर आधारित प्रत्येक इंटरफेस के लिए एक ठोस कार्यान्वयन बनाना है।

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

आपके सार कारखाने का प्रत्येक ठोस कार्यान्वयन आपके डिवाइस प्रकार के आधार पर कई इंटरफ़ेस कार्यान्वयन उत्पन्न कर सकता है।

उदाहरण:

public interface IDeviceFactory 
{ 
     ISomething GetSomeInterface(); 
     ISomethingElse GetSomeOtherInterface(); 
} 

और फिर आप प्रत्येक डिवाइस के लिए विशेष कारखाने को लागू:

public class SimpleDeviceFactory : IDeviceFactory 
{ 
    public virtual ISomething GetSomeInterface() 
    { return Something.Empty; } 

    public virtual ISomethingElse GetSomeOtherInterface() 
    { return new SomeSimpleConreteImplementation(); } 
} 

या हो सकता है:

public class ComplexDeviceFactory : IDeviceFactory 
{ 
    public virtual ISomething GetSomeInterface() 
    { return new ComplexStuff(); } 

    public virtual ISomethingElse GetSomeOtherInterface() 
    { return new EvenMoreComplexStuff(); } 
} 

और फिर, अंत में, आप सही बनाने आपके डिवाइस के लिए कारखाना:

public class DeviceFactory 
{ 
    public static IDeviceFactory CreateForDevice(IDevice device) 
    { 
      DeviceType type = device.Type; // or something like this 
      switch (type) 
      { 
       case DeviceType.Simple: 
       return new SimpleDeviceFactory(); 

       case DeviceType.Complex: 
       return new ComplexDeviceFactory(); 

       default: 
       throw new NotImplementedException(); 
      } 
    } 
} 

ध्यान दें कि मैंने आईडीवीस फैक्ट्री विधि कार्यान्वयन को virtual के रूप में भी चिह्नित किया है, ताकि आप किसी विशिष्ट डिवाइस के लिए विशिष्ट इंटरफेस को आसानी से पुन: उपयोग या ओवरराइड कर सकें।

+0

धन्यवाद ग्रू, यह वास्तव में समस्या का एक सीधा दृष्टिकोण है! जैसा कि मैंने अपने मूल प्रश्न पर अपनी टिप्पणी में कहा था, मैं कोड "डिवाइस केंद्रित" (प्रत्येक संभावित डिवाइस के लिए कक्षाएं बनाने) को बनाने के लिए और डिवाइस से फीडबैक के आधार पर बनाई गई ऑब्जेक्ट को बनाना चाहता हूं (यह क्या करने में सक्षम है कर)। –

0

.NET 4 इसे आसान बना सकता है, आप पहले से ही निर्दिष्ट फ्रेमवर्क में से एक का उपयोग कर सकते हैं या सिस्टम पर जा सकते हैं। रिफ्लेक्शन मार्ग। आपको इंटरनेट पर बहुत सारे नमूने मिलेंगे।

मैंने पहले दोनों किया है। अपनी खुद की आईएल रोलिंग। सामान स्वीकार करें और एक ढांचे का उपयोग (मेरे मामले में Spring.NET)। छोटी चीजों के अलावा कुछ भी के लिए, ढांचे में से एक का उपयोग करें।

0

आप Re-mix प्रोजेक्ट के साथ भी प्रयास कर सकते हैं। इस परियोजना की मुख्य विशेषताओं में से एक mixins बनाता है, जो आपको कार्यान्वयन के साथ इंटरफेस जोड़ने और अन्य वर्गों के लिए राज्य जोड़ने देता है। एक नज़र इस उदाहरण लें:

using Remotion.Mixins; 
using Remotion.TypePipe; 
//... 

public interface ITargetInterface 
{ 
    void DoSomething(); 
} 
// . . . 
public class TargetImplementation : ITargetInterface 
{ 
    public void DoSomething() 
    { 
     Console.WriteLine("ITargetInterface.DoSomething()"); 
    } 
} 
// . . . 
public interface IMixinInterfaceA 
{ 
    void MethodA(); 
} 
// . . . 
public class MixinImplementationA : IMixinInterfaceA 
{ 
    public void MethodA() 
    { 
     Console.WriteLine("IMixinInterfaceA.MethodA()"); 
    } 
} 
// . . . 
public interface IMixinInterfaceB 
{ 
    void MethodB(int parameter); 
} 

// . . . 
public class MixinImplementationB : IMixinInterfaceB 
{ 
    public void MethodB(int parameter) 
    { 
     Console.WriteLine("IMixinInterfaceB.MethodB({0})", parameter); 
    } 
} 

तो फिर तुम एक mixin बनाने के लिए उन प्रकार मर्ज कर सकते हैं:

var config = MixinConfiguration.BuildFromActive() 
      .ForClass<TargetImplementation>() 
      .AddMixin<MixinImplementationA>() 
      .AddMixin<MixinImplementationB>() 
      .BuildConfiguration(); 
MixinConfiguration.SetActiveConfiguration(config); 

दुर्भाग्य से, आप बस TargetImplementation पर नया फोन नहीं कर सकते हैं और एक mixin की उम्मीद है। इसके बजाय, आपको TargetImplementation इंस्टेंस बनाने के लिए री-मिक्स से पूछना होगा ताकि यह आपके विनिर्देश के लिए एक नया प्रकार बना सके और इसे तुरंत चालू कर सके। जब इसे TargetImplementation के उदाहरण के लिए कहा जाता है, तो यह एक मिश्रण को वापस कर देगा जिसमें सभी इंटरफेस और कक्षाएं संयुक्त होंगी।

ITargetInterface target = ObjectFactory.Create<TargetImplementation>(ParamList.Empty); 

target.DoSomething(); 

var targetAsMixinA = target as IMixinInterfaceA; 
if (targetAsMixinA != null) 
{ 
    targetAsMixinA.MethodA(); 
} 

var targetAsMixinB = target as IMixinInterfaceB; 
if (targetAsMixinB != null) 
{ 
    targetAsMixinB.MethodB(30); 
} 
संबंधित मुद्दे