2010-07-04 18 views
11

मैं यह निर्धारित करना चाहता हूं कि मेरे पास किस प्रकार का कस्टम क्लास प्रकार (MyClass) है या फ्रेमवर्क (System.String) द्वारा प्रदान किया गया है।मैं कैसे निर्धारित करूं कि System.Type एक कस्टम प्रकार या फ्रेमवर्क प्रकार है या नहीं?

क्या प्रतिबिंब में कोई तरीका है कि मैं अपने वर्ग प्रकार को system.string या अन्य फ्रेमवर्क प्रदान किए गए प्रकारों से अलग कर सकता हूं?

+4

आपको परवाह क्यों है? –

उत्तर

7

एक ही रास्ता सुरक्षित रूप से करने के लिए:

संपादित

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

//add more .Net BCL names as necessary 
var systemNames = new HashSet<string> 
{ 
"mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089", 
"System.Core, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" 
}; 

var isSystemType = systemNames.Contains(objToTest.GetType().Assembly.FullName); 

एक थोड़ा कम भंगुर समाधान AssemblyName वर्ग का उपयोग करें और छोड़ संस्करण संख्या/संस्कृति की जांच करने के लिए है। यह निश्चित रूप से मानता है कि सार्वजनिक कुंजी संस्करणों के बीच नहीं बदलती है।

//add more .Net BCL names as necessary 
var systemNames = new List<AssemblyName> 
{ 
new AssemblyName ("mscorlib, Version=4.0.0.0, Culture=neutral, " + 
        "PublicKeyToken=b77a5c561934e089"), 
new AssemblyName ("System.Core, Version=4.0.0.0, Culture=neutral, "+ 
        "PublicKeyToken=b77a5c561934e089") 
}; 

var obj = GetObjectToTest(); 

var objAN = new AssemblyName(obj.GetType().Assembly.FullName); 

bool isSystemType = systemNames.Any(
     n => n.Name == objAN.Name 
      && n.GetPublicKeyToken().SequenceEqual(objAN.GetPublicKeyToken())); 

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

4

आप उस विधानसभा की जांच कर सकते हैं जिसमें प्रकार घोषित किया गया है।

object.GetType().Assembly 
+3

तो सवाल यह है कि कैसे पता होना चाहिए कि एक असेंबली .NET ढांचे का हिस्सा है? –

5

आप बस तो आप सीधे उन प्रकार के लिए जाँच कर सकते हैं MyClass और string के बीच भेद करना चाहते हैं:

Type typeToTest = GetTypeFromSomewhere(); 

if (typeToTest == typeof(MyClass)) 
    MyClassAction(); 
else if (typeToTest == typeof(string)) 
    StringAction(); 
else 
    NotMyClassOrString(); 

आप या नहीं, किसी दिए गए प्रकार एक रूपरेखा है के लिए एक अधिक सामान्य जांच की जरूरत है तो आप किस प्रकार की जांच कर सकता है कि क्या यह System नाम स्थान के अंतर्गत आता है:

// create an array of the various public key tokens used by system assemblies 
byte[][] systemTokens = 
    { 
     typeof(System.Object) 
      .Assembly.GetName().GetPublicKeyToken(), // B7 7A 5C 56 19 34 E0 89 
     typeof(System.Web.HttpRequest) 
      .Assembly.GetName().GetPublicKeyToken(), // B0 3F 5F 7F 11 D5 0A 3A 
     typeof(System.Workflow.Runtime.WorkflowStatus) 
      .Assembly.GetName().GetPublicKeyToken() // 31 BF 38 56 AD 36 4E 35 
    }; 

Type typeToTest = GetTypeFromSomewhere(); 

string ns = typeToTest.Namespace; 
byte[] token = typeToTest.Assembly.GetName().GetPublicKeyToken(); 

bool isSystemType = ((ns == "System") || ns.StartsWith("System.")) 
        && systemTokens.Any(t => t.SequenceEqual(token)); 
+0

वास्तव में बुलेटप्रूफ नहीं है, अगर नामस्थान को "SystemUtil" कहा जाता है;) –

+0

@ थॉमस: मुझे एहसास हुआ कि पोस्टिंग के तुरंत बाद मुझे संपादित करने से पहले दूर बुलाया गया था। अब तय – LukeH

+0

मुझे पूरा यकीन है कि आप वास्तव में अपनी खुद की असेंबली लिख सकते हैं और नेमस्पेस 'सिस्टम बना सकते हैं। [कुछ]' ... मैं ऐसा करने का बड़ा प्रशंसक नहीं हूं, लेकिन मुझे कुछ खुली स्रोत परियोजनाएं पता हैं - उदाहरण के लिए , ['System.Data.SQLite'] (http://sqlite.phxsoftware.com/), [' System.Drawing.Html'] (http://htmlrenderer.codeplex.com/)। –

0

नहीं सभी फ्रेमवर्क वर्गों Sys में शुरू टेम्प नेमस्पेस (वे माइक्रोसॉफ्ट आदि भी हो सकते हैं)।

जैसे, आप शायद प्रकार का है कि आप के रूप में ऐसे परीक्षण कर रहे हैं के साथ एक ज्ञात ढांचा वर्ग के स्थान की तुलना कर सकते:

if (String.CompareOrdinal(
     Path.GetDirectoryName(typeof(String).Assembly.Location), 
     Path.GetDirectoryName(typeof(MyType).Assembly.Location) 
    ) == 0) 
    { 
    //Framework Type 
    } 
    else 
    { 
    //3rd Party DLL 
    } 

नहीं सबसे बड़ी समाधान; लेकिन सिस्टमस्पेस सिस्टम के साथ शुरू होने पर परीक्षण करने से सुरक्षित है (मैं एक नामस्थान बना सकता हूं जो सिस्टम के साथ शुरू होता है जो ढांचा वर्ग नहीं है)।

typeof(MyType).Assembly.GlobalAssemblyCache 
+2

जहां तक ​​मुझे पता है, बीसीएल में केवल 'सिस्टम' * नामस्थान शामिल हैं। 'माइक्रोसॉफ्ट। *' नामस्थान बीसीएल का एक सुपरसेट है - कभी-कभी एफसीएल के रूप में जाना जाता है - और ईसीएमए सीएलआई मानक का हिस्सा नहीं हैं। http://en.wikipedia.org/wiki/Base_Class_Library – LukeH

+0

@LukeH: वास्तव में अच्छा बिंदु। जिस महत्वपूर्ण बिंदु के लिए मैं जा रहा था वह सिस्टम से शुरू होने वाले नामस्थान पर भरोसा नहीं करना था। और जैसा कि अन्य समाधान दिखाए गए हैं, खोजना हमेशा सर्वोत्तम शर्त है; यह एक "गरीब आदमी" चेक है जिसे मैंने सोचा था कि मैं बस मामले में फेंक दूंगा। –

1

जांच करें कि विधानसभा CLR पुस्तकालय के अंतर्गत आता है:

myType.Module.ScopeName == "CommonLanguageRuntimeLibrary" 

रूप here समझाया।

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

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