2012-10-10 14 views
10

जब मैं वर्तमान AppDomain में सभी प्रकार की सूची बनाना, मैं सामान्य प्लेसहोल्डर के साथ मेरी सामान्य प्रकार देख से बनाया गया है प्रकार के बंद कर दिया। हालांकि, अगर मैं अपने जेनेरिक प्रकारों को एक प्रकार के साथ चालू करता हूं और फिर ऐपडोमेन में सभी प्रकार की सूची देता हूं, तो मुझे नए बनाए गए बंद प्रकार दिखाई नहीं देते हैं।सूची है जो रनटाइम खुला सामान्य प्रकार

नीचे दिए गए उदाहरण में, उत्पादन केवल है:

Foo`1[T] 

मैं बंद प्रकार के लिए देख रहा हूँ:

Foo`1[System.Int32] 

वहाँ बंद प्रकार क्रम है कि देखने के लिए एक रास्ता है मेरे खुले जेनेरिक प्रकारों के आधार पर मेरे लिए बनाया गया है?

class Foo<T> 
{ 
} 

class Program 
{ 
    static void Main(string[] args) 
    { 
     var tmp = new Foo<int>(); 
     ListTypes(); 
    } 

    private static void ListTypes() 
    { 
     var types = from assembly in AppDomain.CurrentDomain.GetAssemblies() 
         from type in assembly.GetTypes() 
         where type.Name.Contains("Foo") 
         select type; 

     foreach (var type in types) 
      Console.WriteLine(type.ToString()); 
    } 
} 

मैंने बंद प्रकार की खोज की उम्मीद में सामान्य तर्क से सभी प्रकारों को खोजने का भी प्रयास किया है।

class Foo<T> 
{ 
} 

class Bar 
{ 
} 

class Program 
{ 
    static void Main(string[] args) 
    { 
     var tmp = new Foo<Bar>(); 
     ListTypes(); 
    } 

    private static void ListTypes() 
    { 
     var types = from assembly in AppDomain.CurrentDomain.GetAssemblies() 
         from type in assembly.GetTypes() 
         where type.IsGenericType 
         && type.GetGenericArguments().Contains(typeof(Bar)) 
         select type; 

     foreach (var type in types) 
      Console.WriteLine(type.ToString()); 
    } 
} 

यह मेरी जिज्ञासा को पूरा करने के लिए है।

+0

यदि मैं सही ढंग से समझता हूं, तो यह प्रतिबिंब केवल मेटाडेटा में परिभाषित प्रकार प्राप्त करेगा, जिसमें आपके मामले में सामान्य प्रकार की परिभाषा शामिल है। चूंकि विशिष्ट प्रकारों को जेनेरिक प्रकारों से गतिशील रूप से रनटाइम पर बनाया जा सकता है (फिर से सामान्य तर्कों में गुजरने के प्रतिबिंब का उपयोग करके) - आप देख सकते हैं कि मेटाडेटा में उन्हें डालने का कोई तरीका नहीं है ... इसलिए, कुछ अन्य तंत्र (नहीं मेटाडाटा एक्सप्लोरेशन) को बनाए गए विशिष्ट प्रकारों को खोजने के लिए उपयोग किया जाना चाहिए। –

+0

मैं देखता हूं। यह बताता है कि मैं रनटाइम पर बनाए गए प्रकारों को क्यों नहीं देख सकता, वे मेटाडेटा में नहीं हैं कि प्रतिबिंब पूछताछ कर रहा है। मुझे आश्चर्य है कि वह अन्य तंत्र क्या होगा? –

+1

टाइपस्मेपर्स नामक mscorlib के अंदर एक निजी प्रकार है जिसमें स्ट्रिंग्स की एक सरणी लौटने वाली गेटनेम विधि है, लेकिन जब मैं प्रतिबिंब के तहत इसका उपयोग करने की कोशिश कर रहा हूं तो मुझे गंभीर याद आ रही है कि मुझे COM ऑब्जेक्ट्स और इंटरऑप के बारे में कितना पता है, और आम तौर पर मुझे mscorlib के अंदर निजी प्रकार के साथ गड़बड़ नहीं करना चाहिए :-P फिर भी एक सुरुचिपूर्ण समाधान की तलाश में है। –

उत्तर

5

जहां तक ​​मेरा इस मामले Foo<T> में समझ सकते हैं एक खुला अनबाउंड सामान्य प्रकार है, इसलिए क्रम में CLR एक खाका/कंकाल के रूप में उपयोग होगा निर्माण करने के लिए और प्रकार पैरामीटर निर्दिष्ट प्रकार के साथ एक सामान्य प्रकार बंद (Foo<int> , Foo<object>, आदि)। तो मूल रूप से Foo<int>Foo<T> कंकाल का एक रनटाइम निर्मित कार्यान्वयन है।

अब, रन-टाइम में आप Foo<int> के प्रकार या तो typeof(Foo<int>) या typeof(Foo<>).MakeGenericType(new[] { typeof(int) }) का उपयोग करके प्राप्त कर सकते हैं और यह एक ही Type नहीं है और यह कोई मतलब नहीं होगा यह होने के लिए। लेकिन करीब देखो और आप देखेंगे कि typeof(Foo<T>) और typeof(Foo<int>) दोनों समान मेटाडेटा टोकन और GUID साझा करते हैं।

एक और दिलचस्प बात यह है कि typeof(Foo<int>).Assembly वह होगा जो आप उम्मीद करेंगे, लेकिन जैसा कि आपने पहले ही देखा है कि आप विधानसभा से उस प्रकार को नहीं प्राप्त कर सकते हैं।

क्योंकि Foo<int> विधानसभा में परिभाषित नहीं है यही कारण है कि (यदि आप परावर्तक/ILSpy साथ विधानसभा मेटाडाटा जांच कर सकते हैं)। रन-टाइम में CLR बनाने Foo<int> के लिए ("का निर्माण") एक विशेष ("बंद") Foo<T> के संस्करण होगा (ताकि - एक असीम खुला सामान्य प्रकार परिभाषा का निर्माण बंद प्रकार) है और यह एक Type "देने"। इसलिए जब तक सीएलआर सीधे किसी भी तरह से बंद न हो, बंद जेनेरिक प्रकारों की सूची जो रन-टाइम पर उत्पन्न होती है, आप भाग्य से बाहर हैं।

इसके अलावा यहां एक टुकड़ा इस बात की पुष्टि कर सकते हैं कि मैं क्या कह रहा हूँ है:

हालांकि इस तरह के नोड < फार्म> और नोड < स्ट्रिंग के रूप में एक सामान्य प्रकार,> में से प्रत्येक के निर्माण, का अपना अलग प्रकार है पहचान, CLR सक्षम प्रकार instantiations के बीच वास्तविक JIT-संकलित कोड की ज्यादा का पुन: उपयोग किया जा सके। यह काफी कोड ब्लोट कम कर देता है और क्योंकि एक सामान्य प्रकार के विभिन्न instantiations रन टाइम पर विस्तार कर रहे हैं संभव है। संकलन समय पर एक निर्मित प्रकार के सभी मौजूद हैं प्रकार संदर्भ। विधानसभाओं ए और बी दोनों संदर्भ जब एक सामान्य प्रकार एक तिहाई विधानसभा में परिभाषित किया गया है, उनके निर्माण प्रकार रन टाइम पर विस्तार कर रहे हैं।इसका मतलब यह है कि, सीएलआर प्रकार-पहचान (जब उचित हो) साझा करने के अलावा, असेंबली ए और बी से तत्काल टाइप करें रन-टाइम संसाधन जैसे देशी कोड और विस्तारित मेटाडेटा साझा करें।

http://msdn.microsoft.com/en-us/magazine/cc163683.aspx

+2

यह कुछ भारी "रन-टाइम सीएलआर जादू" है: फू के स्थिर कन्स्ट्रक्टर को प्रत्येक बंद प्रकार "लोडिंग" के लिए बुलाया जाता है :-) पीएस स्कीट कहां है जब आपको उसकी ज़रूरत है? –

1
इवान के जवाब

ज्यादातर सही है, लेकिन यह है कि विधानसभा मेटाडाटा का दावा निर्माण प्रकार के बारे में कोई जानकारी नहीं है काफी सही नहीं है। सभी निर्मित प्रकारों को असेंबली में परिभाषित किया जाता है जो उन्हें उपयोग करता है और मोनो। सेसिल जैसे टूल आपको देखते हैं। रचनात्मक प्रकार प्रतिबिंब के माध्यम से प्रकट नहीं होते हैं और यहां तक ​​कि मोनो। सेसिल उन सभी का पता लगाने में काफी कठिन बनाता है।

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

इस समाधान के लिए दो सीमाएं हैं। सबसे पहले, प्रतिबिंब के माध्यम से निर्मित प्रकार स्वाभाविक रूप से किसी असेंबली में प्रकट नहीं होते हैं। दूसरा, कुछ प्रकार के प्रकार जेनेरिक प्रकारों/विधियों में एम्बेडेड होते हैं और उनके सामान्य प्रकार के तर्क केवल उनके सामान्य प्रकार/विधि के बाद सामान्य जेनेरिक प्रकार तर्कों के साथ तत्काल होते हैं।

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