2012-05-22 15 views
6

मैं वर्तमान में कुछ गतिशील तरीकों को बनाने के लिए जेनेरिक का उपयोग कर रहा हूं, जैसे वस्तु बनाना और मूल्यों के साथ गुण भरना।एक प्रकार से सामान्य चर बनाना - कैसे? या पैरामीटर() के बजाय गुण {} के साथ Activator.CreateInstance() का उपयोग करें?

क्या कोई तरीका जानने के बिना जेनेरिक "गतिशील रूप से" बनाने का कोई तरीका है? उदाहरण के लिए:

List<String> = new List<String>() 

एक predefinied तरीका है, लेकिन

List<(object.GetType())> = new List<(object.GetType()>() 

काम नहीं कर रहा ... लेकिन यह कर सकते हैं?

यह काम नहीं कर रहा (वहाँ एक समान दृष्टिकोण है कि काम करता है है?)

public T CreateObject<T>(Hashtable values) 
    { 
     // If it has parameterless constructor (I check this beforehand) 
     T obj = (T)Activator.CreateInstance(typeof(T)); 

     foreach (System.Reflection.PropertyInfo p in typeof(T).GetProperties()) 
     { 
      // Specifically this doesn't work 
      var propertyValue = (p.PropertyType)values[p.Name]; 
      // Should work if T2 is generic 
      // var propertyValue = (T2)values[p.Name]; 

      obj.GetType().GetProperty(p.Name).SetValue(obj, propertyValue, null); 
     } 
    } 

तो, संक्षेप में: कैसे एक "प्रकार" लेने के लिए और जेनेरिक्स का उपयोग किए बिना कि से एक वस्तु बनाने के लिए? मैंने अभी तक जेनिक्स का उपयोग विधियों में किया है, लेकिन क्या चरों पर उसी तरह उपयोग करना संभव है? मुझे विधि से पहले जेनेरिक (टी) को परिभाषित करना है, तो क्या मैं उन्हें "बनाने" से पहले वैरिएबल पर भी कर सकता हूं?

... या पैरामीटर्स की बजाय गुणों के साथ ऑब्जेक्ट बनाने के लिए "एक्टिवेटर" का उपयोग कैसे करें। आप यहाँ कर की तरह:

// मानकों के साथ महत्व देता

Test t = new Test("Argument1", Argument2); 

// गुण

Test t = new Test { Argument1 = "Hello", Argument2 = 123 }; 

उत्तर

13

आप उपयोग कर सकते हैं MakeGenericType:

Type openListType = typeof(List<>); 
Type genericListType = openListType.MakeGenericType(obj.GetType()); 
object instance = Activator.CreateInstance(genericListType); 
+0

मैं इस मामले में "सूची" का उपयोग नहीं करना चाहता, यह किसी भी वस्तु होना चाहिए। "ओपनलिस्ट टाइप टाइप करें (टाइपफॉफ़ (अज्ञात प्रकार);" – Deukalion

+0

मुझे नहीं लगता कि यह उत्तर ओपी को हल करता है "पैरामीटर() के बजाय गुणों {} के साथ Activeator.CreateInstance() का उपयोग करें।" – Avishek

1

के साथ आप ऑब्जेक्ट प्रारंभकर्ता, (कोई पैरामीटर) यह सिर्फ एक डिफ़ॉल्ट निर्माता उपयोग कर रहा है उपयोग करते हैं, फिर वस्तु के निर्माण के बाद व्यक्तिगत गुणों को सेट करना।

उपरोक्त कोड करीब है - लेकिन var यहां काम नहीं करेगा, क्योंकि यह केवल एक संकलन-समय प्रकार का अनुमान है। के बाद से आप पहले से ही प्रतिबिंब का उपयोग कर रहे हैं, तो आप सिर्फ System.Object उपयोग कर सकते हैं:

object propertyValue = values[p.Name]; 

SetValue कॉल System.Object के साथ ठीक से काम करेगा।

+0

तो मैं कैसे Activator.CreateInstance "ऑब्जेक्ट के साथ उपयोग कर सकते हैं प्रारंभकर्ता "तर्क के रूप में? मुझे यह त्रुटि बताती है कि "इस ऑब्जेक्ट के लिए कोई पैरामीटर रहित कन्स्ट्रक्टर निश्चित नहीं है।" गुणों के प्रकार जिन्हें मैं मान जोड़ने की कोशिश करता हूं वे हैं: स्ट्रिंग, डबल, एनम, बूल। जिस तरह से यह विफल रहता है वह "स्ट्रिंग" है। इसमें कोई पैरामीटर रहित कन्स्ट्रक्टर नहीं है, इसलिए मैं स्ट्रिंग नहीं बना सकता और इसमें मूल्य जोड़ सकता हूं, लेकिन यह कैसे हो सकता है क्योंकि मैं परिभाषित कर सकता हूं: स्ट्रिंग स्ट्र; या स्ट्रिंग str = "यह एक स्ट्रिंग है"; – Deukalion

+0

@Deukalion आपके द्वारा उत्पन्न किए जा रहे प्रकार में पैरामीटर रहित कन्स्ट्रक्टर नहीं है - इसलिए आप इस तकनीक का उपयोग इस के साथ नहीं कर सकते ... –

+0

'स्ट्रिंग स्ट्र = "फू"; वाक्यविन्यास एक सी # भाषा सुविधा है, न कि सीएलआर सुविधा। –

5

आप एक विशेष प्रकार के तर्क के लिए सामान्य प्रकार प्राप्त करने के लिए MakeGenericType विधि का उपयोग कर सकते हैं:

var myObjListType = typeof(List<>).MakeGenericType(myObject.GetType()); 
var myObj = Activator.CreateInstance(myObjListType); 
// MyObj will be an Object variable whose instance is a List<type of myObject> 
+0

लेकिन कहें कि मैं जिस ऑब्जेक्ट को बना रहा हूं वह एक "स्ट्रिंग, बुलियन, इंट, फ्लोट ..." आवश्यक नहीं है। यदि ऑब्जेक्ट गुण को मान पर सेट करने से पहले मुझे इसके लिए एक मान सेट करने की आवश्यकता है। – Deukalion

+0

मूल्य प्रकारों के लिए आपको कोई मान सेट करने की आवश्यकता नहीं है- उनके पास स्वचालित रूप से एक वैध डिफ़ॉल्ट होता है। उदाहरण के लिए, 'bool' प्रकार के फ़ील्ड को' झूठी 'में प्रारंभ करने की आवश्यकता नहीं है, क्योंकि यह स्वचालित रूप से होता है। तारों के लिए, वे शून्य से शुरू करते हैं। यदि आप उन्हें "फ्रेड" जैसे किसी अन्य मूल्य के लिए बनाना चाहते हैं, तो आपको अपना मान "फ्रेड" पर सेट करना होगा। नहीं 'व्यक्ति। फर्स्टनाम = नया स्ट्रिंग ("फ्रेड");', देखो? –