2009-05-12 12 views
17

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

public class ClientBase 
{ } 

public class GenericProxy<T> 
    where T: ClientBase, new() 
{ 
    T _proxy; 

    public GenericProxy(string configName) 
    { 
     _proxy = new T(configName);  
    } 
} 

इस कोड संकलन नहीं है क्योंकि प्रकार टी एक निर्माता है कि एक स्ट्रिंग लेता है करने के लिए गारंटी नहीं है: यहाँ एक नमूना कोड है। क्या सामान्य टी पर एक बाधा परिभाषित करने का कोई तरीका है कि इस प्रकार टी को एक कन्स्ट्रक्टर होना चाहिए जो स्ट्रिंग ले लेता हो? यदि यह संभव नहीं है, तो इस तरह की स्थिति को संभालने के लिए अच्छे विकल्प क्या हैं?

उत्तर

24

यह संभव नहीं है। मैं "static interfaces" देखने के लिए इस संभाल करने के लिए चाहते हैं, लेकिन उन्हें किसी भी समय जल्दी ही उम्मीद नहीं है ...

विकल्प:

  • एक प्रतिनिधि टी
  • के लिए
  • एक और निर्दिष्ट एक कारखाने के रूप में कार्य करने के लिए निर्दिष्ट करें इंटरफ़ेस टी
  • के लिए एक कारखाने के रूप में कार्य करने के लिए प्रारंभ के लिए टी पर ही एक अंतरफलक निर्दिष्ट करें (और एक बाधा ताकि T इंटरफ़ेस लागू करता जोड़ने)

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

public class GenericProxy<T> 
    where T: ClientBase, new() 
{ 
    string _configName; 
    T _proxy; 
    Func<string, T> _factory; 

    public GenericProxy(Func<string, T> factory, string configName) 
    { 
     _configName = configName; 
     _factory = factory; 
     RefreshProxy(); 
    } 

    void RefreshProxy() // As an example; suppose we need to do this later too 
    { 
     _proxy = _factory(_configName); 
    } 
} 

1

जैसा कि जॉन नोट करता है, इसके लिए कोई अंतर्निहित समर्थन नहीं है - लेकिन एक तरफ के रूप में आप Expression का उपयोग कर कन्स्ट्रक्टर (प्रतिबिंब से तेज़) में एक टाइप किए गए प्रतिनिधि को बना सकते हैं। ऐसा करने के लिए कोड MiscUtil में पाया जा सकता है (MiscUtil.Linq.Extensions.TypeExt में)।

1

यह अपने वास्तविक सवाल का जवाब नहीं है, एक विधि को बाधित करने के लिए, लेकिन पूर्णता इस तरीके से प्रतिबिंब का उपयोग क्या आप रन टाइम पर पूछ रहे हैं क्या कर सकते हैं, है: एक पूर्ण काम कर उदाहरण आधारित है

private T Get<T>(string id) 
    { 
    var constructor = typeof(T).GetConstructor(new Type[] { typeof(X), typeof(Y) }); 
    if (constructor == null) throw new InvalidOperationException("The type submitted, " + typeof(T).Name + ", does not support the expected constructor (X, Y)."); 

    var data = GetData(id); 
    return (T)constructor.Invoke(new object[] { data.x, data.y }); 
    } 
0

यहाँ @JonSkeet जवाब पर: ice cream

:

using System; 
using System.Collections.Generic; 

namespace GenericProxy 
{ 
    class Program 
    { 
     static void Main() 
     { 
      GenericProxy<ClientBase> proxy = new GenericProxy<ClientBase>(ClientBase.Factory, "cream"); 

      Console.WriteLine(proxy.Proxy.ConfigName); // test to see it working 
     } 
    } 

    public class ClientBase 
    { 
     static public ClientBase Factory(string configName) 
     { 
      return new ClientBase(configName); 
     } 

     // default constructor as required by new() constraint 
     public ClientBase() { } 

     // constructor that takes arguments 
     public ClientBase(string configName) { _configName = configName; } 

     // simple method to demonstrate working example 
     public string ConfigName 
     { 
      get { return "ice " + _configName; } 
     } 

     private string _configName; 
    } 

    public class GenericProxy<T> 
     where T : ClientBase, new() 
    { 
     public GenericProxy(Func<string, T> factory, string configName) 
     { 
      Proxy = factory(configName); 
     } 

     public T Proxy { get; private set; } 
    } 
} 

निम्नलिखित उत्पादन को देखने के लिए की अपेक्षा करें

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

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