2010-04-12 8 views

उत्तर

0

संपादित करें: कृपया ध्यान दें कि यह उत्तर किसी संपादन में पूरी तरह से परिवर्तित होने से पहले दिया गया था। इसके कारण, अब यह उन चीजों को संदर्भित करता है जो मूल रूप से बताए गए प्रश्न में मौजूद थे। मैं सभी "लटकने वाले पॉइंटर्स" के लिए क्षमा चाहता हूं। :-)


लघु जवाब:

कोड द्वारा पोस्ट की गई साथ

, मैं नहीं एक विकल्प IFoo<T> पर कास्ट करने के लिए दिख रहा है। यदि आप नहीं करते हैं, तो संकलक चेतावनी देगा (मेरी मशीन पर, कम से कम)।

अधिक विस्तृत जवाब:

अपने कोड वास्तव में उस तरह से होना जरूरी है? अधिक विशेष रूप से, क्या आपको पहले स्थान पर प्रश्न में कलाकारों की आवश्यकता है?

var stringFoo = FooFactory.CreateFoo<string>(); 

आप टेम्पलेट पैरामीटर (string इस मामले में) प्रदान करने के लिए स्पष्ट रूप से, क्योंकि यह किसी भी तरीके से तर्क से प्राप्त नहीं किया जा सकता:

मैं तुम्हें अपने कारखाने विधि और अधिक या कम इस तरह कॉल करने के लिए जा रहे हैं मान (इस मामले में क्योंकि वास्तव में कोई भी वास्तव में नहीं है)। जाहिर है, कारखाना विधि IFoo<string> लौटाएगी।

अब

, जब से तुम स्पष्ट रूप से रन-टाइम में प्रकार निर्दिष्ट करने के लिए है, तो आप सिर्फ रूप में अच्छी तरह लिख सकते हैं:

var stringFoo = StringFoo.Create(); 

और इसलिए StringFoo अंदर एक कारखाने विधि है, इस तरह, कि बिना शर्त स्पष्ट करता है :

public class StringFoo : IFoo<string> 
{ 
    ... 

    public static StringFoo Create() // or alternatively, return an IFoo<string> 
    { 
     return new StringFoo(); 
    } 
} 

IFoo<T> कार्यान्वयन भी दूसरे के लिए इस पद्धति को लागू करने, यह आप की बचत होगी if चेन या FooFactory.CreateFoo<T> अंदर switch ब्लॉक, अपने कोड बनाने के द्वारा आसान, और कास्ट करने की आवश्यकता से छुटकारा पाएं (जिसे आप चिंतित हैं)।

मुझे गलत मत समझो, मुझे पता है कि एक से अधिक ऑब्जेक्ट प्रकार का समर्थन करने वाली फैक्ट्री विधियां कुछ मामलों में उपयोगी हैं; लेकिन ऐसा लगता है कि आपके मामले में यह इसके लायक होने की तुलना में अधिक परेशानी का कारण बनता है।


पी.एस .: आप कुछ आईओसी कंटेनर दिलचस्प का एक पहलू हो सकता है।उन्हें आमतौर पर कॉन्फ़िगर करने की आवश्यकता होती है, और इसमें ऐसी प्रक्रिया शामिल होती है जहां आप अमूर्त इंटरफेस के लिए ठोस प्रकार (यानी कार्यान्वयन कक्षाएं) पंजीकृत करते हैं; (उदाहरण के लिए यहाँ Autofac उपयोग करते हुए):

var builder = new ContainerBuilder(); 
builder.RegisterType<StringFoo>().As<IFoo<string>>(); 

फिर बाद में, आप एक वस्तु उदाहरण एक सार प्रकार का अनुरोध कर सकते हैं:

using (var container = builder.Build()) 
{ 
    var stringFoo = container.Resolve<IFoo<string>>(); 
    ... 
} 

Resolve विधि दिलचस्प हिस्सा है। आप इसे एक अमूर्त प्रकार प्रदान करते हैं, और पंजीकृत प्रकारों का उपयोग करते हुए, यह StringFoo प्रकार की एक ठोस वस्तु वापस कर देगा। इसे देखो, अगर यह आपको ज्यादा पसंद नहीं करता है! :-)

+0

डाउनवॉटर के लिए: क्यों, अगर मैं पूछ सकता हूं? – stakx

+0

@ मेरिट, कोई चिंता नहीं। आखिरकार, हम सब यहाँ सीखने के लिए नहीं हैं? मुझे यह सब कुछ लिखने में कोई फर्क नहीं पड़ता, क्योंकि मुझे लगता है कि मैं लेखन/व्याख्या से भी बहुत लाभ कमा सकता हूं। – stakx

0

का डुप्लिकेट आप समस्या आप इस तंत्र के साथ हल करते वर्णन कर सकते है? इससे संपर्क करने का सबसे स्पष्ट तरीका है।

संपादित

और हाँ, कोड बदबू आ रही है। आपने किसी भी प्रकार के लिए कमरे को खुला छोड़ दिया है, सिवाय इसके कि आप उसे एक ही प्रकार में बाध्य करते हैं, और रन-टाइम अपवाद उत्पन्न करते हैं। उस मामले में एक प्रकार पैरामीटर क्यों है?

+3

नहीं, मैं नहीं हूं। मैं एक अमूर्त कारखाने की उपयोगिता को समझ नहीं पा रहा हूं जो एक सामान्य इंटरफ़ेस प्रदान करता है लेकिन आखिरकार केवल एक विशिष्ट ठोस प्रकार बनाता है। आपने जो वर्णन किया है वह उस समस्या का समाधान है जिसे आपने अभी तक वर्णित नहीं किया है। हमें बताएं कि * यह * समस्या क्या है, इसे हल करने के तरीके की आपकी पूर्वकल्पना के बजाय, और हम आपकी मदद करने में सक्षम होंगे। –

+0

वैक्यूम में प्रौद्योगिकी अक्सर किसी समस्या की तलाश में समाधान में परिणाम देती है। इस तंत्र द्वारा संबोधित स्थितियों को परिभाषित किए बिना, आपके पास कोई मानदंड नहीं है जिसके खिलाफ आप एक मूल्य निर्णय ले सकते हैं। यदि आपका प्रश्न यह निर्धारित करने के लिए और अधिक था कि यह दृष्टिकोण * कुछ * समस्या का व्यवहार्य समाधान है, तो यह अलग है। मैं व्यक्तिगत रूप से एक सामान्य कारखाने के लिए उपयोग नहीं देखता जो सामान्य नहीं है और इस तरह उपयोग किए जाने पर रन-टाइम अपवाद का कारण बनता है। यह ऐसी कार बनाने जैसा है जो तब तक शुरू नहीं होगा जब तक कि आप सुपरमार्केट में नहीं जा रहे हों। –

0

आप कुछ इस तरह की कोशिश कर सकते ...

public static class FooFactory 
{ 
    private static readonly Dictionary<Type, Type> FooTypesLookup; 

    static FooFactory() 
    { 
     FooTypesLookup = (from type in typeof(FooFactory).Assembly.GetExportedTypes() 
          let fooInterface = 
          type.GetInterfaces().FirstOrDefault(
           x => x.IsGenericType && x.GetGenericTypeDefinition() == typeof(IFoo<>)) 
          where fooInterface != null 
          let firstTypeArgument = fooInterface.GetGenericArguments().First() 
          select new { Type = type, TypeArgument = firstTypeArgument }) 
      .ToDictionary(x => x.TypeArgument, x => x.Type); 
    } 

    public static IFoo<T> CreateFoo<T>() 
    { 
     var genericArgumentType = typeof(T); 
     Type closedFooType; 
     return FooTypesLookup.TryGetValue(genericArgumentType, out closedFooType) 
       ? (IFoo<T>) Activator.CreateInstance(closedFooType) 
       : null; 
    } 
} 

या बेहतर अभी तक, अपने पसंदीदा आईओसी कंटेनर (विंडसर, संरचना नक्शा, आदि) लागू करने और सभी प्रकार है कि वहाँ में IFoo लागू रजिस्टर और फिर सक्रियकर्ता के स्थान पर आवश्यक होने पर उन्हें हल करें। क्रिएट इंस्टेंस कॉल।

+0

मेरे लिए लक्ष्य Activator.CreateInstance() का उपयोग नहीं करना था। – Merritt

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