2008-10-24 13 views
9

मैं पहले प्रकार टी वे होगा जानने के बिना एक वर्ग जेनरिक का उपयोग करता है, class<T> तरह के क्रम उदाहरणों पर बनाने के लिए, की जरूरत है, मैं ऐसा ही कुछ करना चाहते हैं:क्या जेनिक्स गतिशील रूप से उपयोग करना असंभव है?

public Dictionary<Type, object> GenerateLists(List<Type> types) 
{ 
    Dictionary<Type, object> lists = new Dictionary<Type, object>(); 

    foreach (Type type in types) 
    { 
     lists.Add(type, new List<type>()); /* this new List<type>() doesn't work */ 
    } 

    return lists; 
} 

... लेकिन मैं नहीं कर सकता। मुझे लगता है कि जेनेरिक ब्रैकेट्स के अंदर एक प्रकार चर के अंदर सी # में लिखना संभव नहीं है। क्या ऐसा करने का कोई और तरीका है?

+0

क्या आप एक कारण दे सकते हैं कि आप रनटाइम पर एक प्रकार सुरक्षित जेनेरिक ऑब्जेक्ट क्यों बनाना चाहते हैं? –

+0

मैंने इसे कई बार किया है, खासकर जब प्रोटोकॉल बफर पोर्टिंग करते हैं। –

+0

मैं अपने काम में एक दृढ़ता ढांचे के लिए एक एडाप्टर कर रहा हूं, और कक्षाओं को इस जानकारी को अपना काम करने की आवश्यकता है। –

उत्तर

17

आप ऐसा नहीं कर सकते - जेनरिक की बात ज्यादातर संकलन समय प्रकार-सुरक्षा है - लेकिन आप प्रतिबिंब के साथ यह कर सकते हैं:

public Dictionary<Type, object> GenerateLists(List<Type> types) 
{ 
    Dictionary<Type, object> lists = new Dictionary<Type, object>(); 

    foreach (Type type in types) 
    { 
     Type genericList = typeof(List<>).MakeGenericType(type); 
     lists.Add(type, Activator.CreateInstance(genericList)); 
    } 

    return lists; 
} 
+0

फिर से धन्यवाद जॉन। क्या CreateInstance को एक खाली कन्स्ट्रक्टर की आवश्यकता है? मेरे पास यह नहीं है, वास्तव में मुझे इसमें पैरामीटर इनपुट करने की आवश्यकता है। –

+0

इसे एक निर्माता की आवश्यकता है। यदि आप एक कन्स्ट्रक्टर का उपयोग नहीं करना चाहते हैं तो आप System.Runtime.Serialization असेंबली में FormatterServices.GetUninitializedObject() का उपयोग कर सकते हैं। –

+1

@ विक्टर: एक्टिवेटर के ओवरलोड हैं। क्रिएट इंस्टेंस जो पैरामीटर लेते हैं, या आप Type.GetConstructor का उपयोग कर सकते हैं और फिर उसे आमंत्रित कर सकते हैं। असल में एक प्रकार से किसी प्रकार के उदाहरण के लिए जाने के कई तरीके हैं - एक चुनें :) –

4

कितनी बार कर रहे हैं पर निर्भर करता है एक्टिवेटर का उपयोग करके इस विधि को कॉल करना। क्रिएट इंस्टेंस धीमा हो सकता है। एक और विकल्प ऐसा कुछ करना है:

निजी शब्दकोश> प्रतिनिधि = नया शब्दकोश>();

public Dictionary<Type, object> GenerateLists(List<Type> types) 
    { 
     Dictionary<Type, object> lists = new Dictionary<Type, object>(); 

     foreach (Type type in types) 
     { 
      if (!delegates.ContainsKey(type)) 
       delegates.Add(type, CreateListDelegate(type)); 
      lists.Add(type, delegates[type]()); 
     } 

     return lists; 
    } 

    private Func<object> CreateListDelegate(Type type) 
    { 
     MethodInfo createListMethod = GetType().GetMethod("CreateList"); 
     MethodInfo genericCreateListMethod = createListMethod.MakeGenericMethod(type); 
     return Delegate.CreateDelegate(typeof(Func<object>), this, genericCreateListMethod) as Func<object>; 
    } 

    public object CreateList<T>() 
    { 
     return new List<T>(); 
    } 

पहली तारीख को मारा यह सामान्य विधि है कि सूची बनाता है और फिर एक शब्दकोश में डालता है के लिए एक प्रतिनिधि पैदा हो जाएगी। प्रत्येक आगामी हिट पर आप उस प्रकार के प्रतिनिधि को बस कॉल करेंगे।

आशा है कि इससे मदद मिलती है!

+0

धन्यवाद जॉनी, मैं इस विधि को केवल एक बार कॉल करता हूं, अन्यथा एक प्रतिनिधि रखना एक अच्छा विकल्प होगा। –

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