2012-08-23 13 views
5

जेनेरिक निर्भरता इंजेक्शन हैंडलर (बेस सर्विस लोकेटर) पर काम करते समय मैं जेनेरिक मुद्दे में भाग रहा हूं।"टी टी: कक्षा" बाधा से मेल खाने के लिए आप टी को कक्षा में कैसे डाल सकते हैं?

संपादित करें (स्पष्टता के लिए)

ठीक है तो मैं वास्तव में एक डि रिसोल्वर के रूप में SimpleInjector उपयोग कर रहा हूँ और उस पर वर्ग बाधा है 1 GetInstance विधि है, तो यहाँ कुछ और पूरा कोड है:

public T GetInstance<T>() where T : class 
    { 
    try 
    { 
     // works 
     return _container.GetInstance<T>(); 
    } 
    catch(ActivationException aEx) 
    { 
     return default(T); 
    } 
    } 

    public T GetInstance<T>() 
    { 
    try 
    { 
     if(typeof(T).IsClass) 
     { 
      // does not work, T is not a reference type 
      return _container.GetInstance<T>(); 
     } 
    } 
    catch(ActivationException aEx) 
    { 
     return default(T); 
    } 
    } 

संपादित 2 - अंतिम कोड के बाद से यह टिप्पणी में अजीब लग:

public T GetInstance<T>() 
    { 
    try 
    { 
     if(typeof(T).IsClass) 
     { 
      return (T) _container.GetInstance(typeof(T)); 
     } 
    } 
    catch(ActivationException aEx) 
    { 
     return default(T); 
    } 
    } 
+5

शायद अगर हम एक लौटने अशक्त उदाहरण से अलग कारणों के बारे में यदि आप ऐसा करने में रुचि रखते हैं और अधिक पता था, ...? इसे ढांचा बनाने का एक बेहतर तरीका हो सकता है। –

+0

कृपया संपादन 1 देखें कि मैं ऐसा क्यों करना चाहता हूं। – Laurence

उत्तर

1

आप एक और सहायक विधि का उपयोग कर सकते हैं? कृपया परीक्षण वर्ग

public class Test 
{ 
    public T GetInstance<T>() where T : class 
    { 
    return (T)GetInstance(typeof(T)); 
    } 

    private object GetInstance(Type type) 
    { 
    return Activator.CreateInstance(type); 
    } 

    public T GetEvenMoreGenericInstance<T>() 
    { 
    if(!typeof(T).IsValueType) 
    { 
     return (T)GetInstance(typeof(T)); 
    } 
    return default(T); 
    } 
} 
+0

वास्तव में काम करता है, धन्यवाद। मैं टी के लिए कास्टिंग के बारे में भूल: 'सार्वजनिक टी GetInstance () { कोशिश { अगर (typeof (टी) .IsClass) { वापसी (टी) _container.GetInstance (typeof (टी)); } } पकड़ (सक्रियण अपवाद एईएक्स) { वापसी डिफ़ॉल्ट (टी); } } ' – Laurence

1

संक्षिप्त उत्तर यह है कि आप कम से कम नहीं, ऐसा नहीं कर सकते हैं। संकलक को पूरी तरह से गारंटी देने के लिए बहुत सारे काम करना होगा कि टी हमेशा आपकी स्थिति में एक कक्षा होगी, इसलिए यह आपको GetEvenMoreGenericInstance पर एक ही प्रकार की बाधा लागू किए बिना सामान्य प्रकार पैरामीटर के रूप में पारित करने नहीं देगा।

आप इसे प्रतिबिंब के माध्यम से पूरा कर सकते हैं, या GetInstance का एक गैर-सामान्य अधिभार बना सकते हैं जो पैरामीटर के रूप में एक प्रकार लेता है। मैं टाइप पैरामीटर विकल्प की सिफारिश करता हूं, या इस विधि को कॉल करने की आवश्यकता को खत्म करने के लिए पूरी तरह से अपने कोड को पुनर्गठन करता हूं।

0

नीचे आप प्रतिबिंब का उपयोग GetInstance का एक संस्करण को खोजने के लिए कर सकता है, तो उपयुक्त एक फोन मिला।

निम्न उदाहरण स्थिर तरीकों को कॉल करता है, लेकिन आप इसे विस्तार कर सकते हैं:

namespace Scratch 
{ 
    internal class Foo 
    { 
     // A class to create 
    } 

    class Program 
    { 
     public static T GetInstance<T>() where T : class, new() 
     { 
      return new T(); // Or whatever... 
     } 

     public static T CallGeneric<T>(Func<object> f) 
     { 
      var method = f.Method; 

      var converted = method.GetGenericMethodDefinition().MakeGenericMethod(typeof(T)); 

      return (T) converted.Invoke(null, new object[] {}); 
     } 

     public static T GetEvenMoreGenericInstance<T>() 
     { 
      if(!typeof(T).IsValueType) 
      { 
       return CallGeneric<T>(GetInstance<object>); 
      } 
      return default(T); 
     } 

     static void Main(string[] args) 
     { 
      var a = GetEvenMoreGenericInstance<int>(); 
      var b = GetEvenMoreGenericInstance<Foo>(); 
     } 
    } 
} 
+0

मुझे प्रतिबिंब के उपयोग पसंद है :) – Laurence

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