2009-08-18 7 views
5

देखें मैं इस तरह एक स्थिति है ...दर्रा प्रकार गतिशील करने के लिए <T>

object myRoledata = List<Roles>() --> (some list or Ienumerable type) 

अब मैं एक सामान्य विधि है जहाँ से List<T> एक XML वस्तु बनाता है - कुछ इस तरह ..

public string GetXML<T>(object listdata) 
{ 
    List<T> objLists = (List<T>)Convert.ChangeType(listData, typeof(List<T>)); 
    foreach(var obj in listdata) 
    { 
     //logic to create xml 
    } 
} 

अब इस विधि मैं इस तरह करना है चलाने के लिए:

string xml = GetXML<Roles>(myRoledata); 

अब मुझे नहीं पता कि Type मुझे GetXML विधि में पारित करने के लिए आ सकता है। मेरे पास एक विधि है जो अलग-अलग Type एस के लिए GetXML पर कॉल करेगी। Roles, Users आदि

अब मैं TypeList<> के भीतर इस

Type genericType = obj.GetType().GetGenericArguments()[0]; 

की तरह प्राप्त कर सकते हैं, लेकिन यह

string xml = GetXML<genericType>(myRoledata); 

है जैसे कि यह पारित नहीं हो सकता वहाँ वैसे भी है, जिसमें मैं किसी भी genericTypes को पारित कर सकते हैं है GetXML विधि?

+0

शायद आप इस सवाल में स्पष्ट करना चाहते हैं कि (संभवतः एकाधिक) प्रकार टी टी संकलित समय पर अज्ञात हैं या नहीं। यदि वे ज्ञात हैं तो Ulrik का जवाब समझ में आता है, यानी तर्क प्रकार को रोकना और बल देना (शायद कई ओवरलोड के साथ)। यदि यह ज्ञात नहीं है कि आपको कुछ रूपों में प्रतिबिंब का उपयोग करना चाहिए, और मार्क उत्तर यह प्राप्त करने के लिए सबसे सरल और संभावित तरीका दिखाता है। – ShuggyCoUk

उत्तर

2

यह एक समस्या है जिसे आप शायद से बचने के लिए चाहते हैं। यह प्रतिबिंब के माध्यम से, यथासंभव हल किए बिना विधियों को गतिशील रूप से कॉल करने के लिए संभव है - लेकिन यह प्रकार-एनोटेशन के पूरे बिंदु को हरा देता है।

या तो यह कार्य करें:

public string GetXML(IEnumerable listdata) { 
    foreach(object obj in listdata) 
     //logic to create xml 
} 

... जो आप अब किसी भी IEnumerable साथ कॉल कर सकते हैं, या इसे लिखने के "आधुनिक" तरीके के रूप में:

public string GetXML(IEnumerable<object> listdata) { 
    foreach(object obj in listdata) 
     //logic to create xml 
} 

... जो आप कर सकते हैं किसी भी IEnumerable के साथ GetXML(someEnumerable.Cast<object>()) और सी # 4.0 में सीधे covariance द्वारा कॉल करें।

आप एक तत्व क्रम के प्रकार की जरूरत है, तो आप इसे प्रत्येक तत्व पर .GetType() का उपयोग कर प्राप्त कर सकते हैं, या आप बस एक पैरामीटर के रूप में यह पारित कर सकते हैं (और पीछे की ओर-संगतता के लिए एक ओवरराइड प्रदान):

public string GetXML(Type elementType, IEnumerable<object> listdata) { 
    foreach(object obj in listdata) 
     //logic to create xml 
} 

public string GetXML<T>(IEnumerable<T> listdata) { 
    return GetXML(typeof(T),listdata.Cast<object>()); 
} 

संयोग से, यदि आप एक्सएमएल का निर्माण कर रहे हैं, तो एक स्ट्रिंग शायद कम मजबूत रिटर्न-प्रकार विकल्प है: यदि संभव हो, तो आप इसके बजाय XElement जैसे कुछ के साथ काम कर सकते हैं - और एक्सएमएल-वैधता गारंटी बूट करने के लिए प्राप्त करें।

+0

असल में, मैं सीधे 'IENumerable 'का उपयोग करने की सलाह दूंगा, कम से कम सी # 4.0 तक; टाइप पैरामीटर में भिन्नता की कमी के कारण यह संभवतः ऐसा नहीं करेगा जो आप चाहते हैं। 'IENumerable' उपयोग करने योग्य से अधिक है। –

+0

ठीक है, विशेष रूप से आईनेमेरेबल के लिए, लिंक 'कैस्ट <>' ऑपरेटर के कारण कॉन्वर्सिस एक समस्या से कम है। यदि आप 'आईनेमरेबल ' पैरामीटर के साथ एक विधि को कॉल करना चाहते हैं और आपके पास कुछ 'टी! = ऑब्जेक्ट 'के साथ' IENumerable myEnum' है, तो आप केवल' myEnum.Cast () 'को पठनीयता में कम नुकसान के साथ कर सकते हैं और गति। गैर-जेनेरिक 'आईनेमरेबल' का स्टाइलिस्ट नुकसान स्पष्ट 'आईडीस्पोजेबल' समर्थन की कमी है, तथ्य यह है कि 'System.Collections' उपयोग के डिफ़ॉल्ट सेट में नहीं है जो VS.NET नई फ़ाइलों में जोड़ता है, और यह एक है कम आम मुहावरे। –

+0

किसी भी मामले में, टिप्पणी के लिए धन्यवाद - गैर-जेनेरिक 'आईन्यूमेरेबल' भी एक बढ़िया विकल्प है। –

7

ऐसा करने के लिए, आपको प्रतिबिंब का उपयोग करने की आवश्यकता है;

typeof(SomeClass).GetMethod("GetXML").MakeGenericMethod(genericType) 
     .Invoke(inst, new object[] {myRoleData}); 

जहां instnull है अगर वह एक स्थिर विधि, this वर्तमान उदाहरण के लिए (इस स्थिति में आप भी typeof(SomeClass) के बजाय GetType() उपयोग कर सकते हैं), या लक्ष्य वस्तु अन्यथा है।

+2

लेकिन क्या यह मूल रूप से गलत नहीं है? इस तरह से विधि का आह्वान करके, जेनेरिक का उपयोग करने के लिए वास्तव में कोई कारण नहीं है, क्योंकि आप टाइप चेक को फेंक देते हैं, और रनटाइम पर अपनी सभी त्रुटियां प्राप्त करते हैं। –

+1

प्रश्न की मेरी व्याख्या यह है कि वे इसे जेनेरिक से हटाना चाहते थे। यदि वह व्याख्या गलत है, तो आपका दृष्टिकोण स्पष्ट रूप से अधिक उपयुक्त है। यह परिदृश्य पर निर्भर करता है ;- –

7

चूंकि आप एक सूची < टी> अपने विधि की पहली पंक्ति में के रूप में अपने listdata पैरामीटर डाली, क्यों तुम सिर्फ विधि हस्ताक्षर

public string GetXML<T>(List<T> listdata) 

इस तरह के परिवर्तन नहीं करते हैं, तो आप की जरूरत नहीं है सामान्य तर्क प्राप्त करने के लिए प्रतिबिंब का उपयोग करने के लिए।

संपादित करें: मुझे लगता है कि आपको IENumerable संग्रह स्वीकार करने में सक्षम होना चाहिए, न केवल सूचियां। तो,

public string GetXML<T>(IEnumerable<T> listdata) 
0

पर आपके विधि हस्ताक्षर को बदलने पर विचार करें आपके पास सही विचार है, लेकिन आप गलत विधि का उपयोग कर रहे हैं। Type.MakeGenericType या MethodInfo.MakeGenericMethod पर एक नज़र डालें। यह आपके उदाहरण की तुलना में कुछ और लाइनें लेगा, लेकिन इसे हल करना आसान होना चाहिए।

GetGenericArguments() को सूची से भूमिकाएं प्राप्त करने के लिए उपयोग किया जा सकता है। यह चारों ओर अलग रास्ता है।

बीटीडब्लू: ऐसा लगता है कि आपके किसी प्रकार का एक्सएमएल क्रमिकरण लागू करना है। पहिया को पुनर्निर्मित करने से पहले सुनिश्चित करें कि आप मौजूदा कक्षाओं की जांच करें।;-)

2

मैं अपनी स्थिति पता नहीं है, लेकिन यह अपने कार्य को फिर से लिखने के लिए संभव है के रूप में:

List<Role> myList; 
GetXML(myList); 

आप प्रकार जोड़ सकते हैं:

public string GetXML<T>(IEnumerable<T> listdata) 
{ 
    foreach(var obj in listdata) 
    { 
     //logic to create xml 
    } 
} 

तो यह के रूप में कहा जा सकता है पैरामीटर जितना समर्थन करने के लिए आवश्यक है, जब तक कि आप कहीं न जाएं, यह पता चले कि ठोस प्रकार क्या है।

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