विधानसभा को बुलाते समय ReflectionTypeLoadException को कैसे रोका जाए ।GetTypes ()


97

मैं इस तरह के कोड का उपयोग करके एक विशिष्ट इंटरफ़ेस को लागू करने वाले प्रकारों के लिए एक असेंबली को स्कैन करने की कोशिश कर रहा हूं:

public List<Type> FindTypesImplementing<T>(string assemblyPath)
{
    var matchingTypes = new List<Type>();
    var asm = Assembly.LoadFrom(assemblyPath);
    foreach (var t in asm.GetTypes())
    {
        if (typeof(T).IsAssignableFrom(t))
            matchingTypes.Add(t);
    }
    return matchingTypes;
}

मेरी समस्या यह है, कि मुझे कुछ मामलों में ReflectionTypeLoadExceptionकॉलिंग मिलती है asm.GetTypes(), उदाहरण के लिए यदि विधानसभा में विधानसभा को संदर्भित करने वाले प्रकार होते हैं जो वर्तमान में उपलब्ध नहीं है।

मेरे मामले में, मुझे उन प्रकारों में कोई दिलचस्पी नहीं है जो समस्या का कारण बनती हैं। जिन प्रकारों को मैं खोज रहा हूं, उन्हें गैर-उपलब्ध असेंबली की आवश्यकता नहीं है।

सवाल यह है कि क्या किसी प्रकार के अपवाद को छोड़ना / अनदेखा करना संभव है, लेकिन फिर भी विधानसभा में निहित अन्य प्रकारों को संसाधित करता है?


1
यह आपके द्वारा ढूंढी जा रही चीज़ों की तुलना में बहुत अधिक दोबारा लिखा जा सकता है, लेकिन MEF आपको समान कार्यक्षमता प्रदान करता है। बस अपनी प्रत्येक कक्षा को एक [निर्यात] टैग के साथ चिह्नित करें जो इंटरफ़ेस को लागू करता है। फिर आप केवल उन इंटरफेस को आयात कर सकते हैं, जो उस समय आपकी रुचि है।
डर्क डस्टर्डली

@ ड्रू, आपकी टिप्पणी के लिए धन्यवाद। मैं MEF का उपयोग करने के बारे में सोच रहा था, लेकिन यह देखना चाहता था कि क्या कोई और सस्ता उपाय है।
M4N

प्लगइन क्लास फैक्ट्री को एक जाना-पहचाना नाम दिया गया है, जिससे आप सिर्फ Activator.CreateInstance () का उपयोग कर सकते हैं। फिर भी, यदि आपको एक विधानसभा समाधान समस्या के कारण अब यह अपवाद मिलता है, तो आप इसे बाद में भी प्राप्त करेंगे।
12:30 पर हंस पसंत

1
@ हंस: मुझे यकीन नहीं है कि मैं पूरी तरह से समझता हूं। मैं जिस असेंबली को स्कैन कर रहा हूं, उसमें दिए गए इंटरफ़ेस को लागू करने वाले किसी भी प्रकार के प्रकार हो सकते हैं, इसलिए एक प्रसिद्ध प्रकार नहीं है। (और यह भी: मैं एक से अधिक असेंबली स्कैन कर रहा हूं, केवल एक ही नहीं)
M4N

2
मेरे पास लगभग एक ही कोड है, और एक ही समस्या है। और मैं जिस विधानसभा का पता लगाता हूं AppDomain.CurrentDomain.GetAssemblies(), वह मेरे मशीन पर काम करती है , लेकिन अन्य मशीनों पर नहीं। क्यों बिल्ली मेरे निष्पादन योग्य से कुछ विधानसभाओं पठनीय / वैसे भी लोड नहीं होगा ??
v.oddou

जवाबों:


130

एक काफी बुरा तरीका होगा:

Type[] types;
try
{
    types = asm.GetTypes();
}
catch (ReflectionTypeLoadException e)
{
    types = e.Types;
}
foreach (var t in types.Where(t => t != null))
{
    ...
}

हालांकि ऐसा करना निश्चित रूप से कष्टप्रद है। आप "क्लाइंट" कोड में इसे अच्छा बनाने के लिए एक एक्सटेंशन विधि का उपयोग कर सकते हैं:

public static IEnumerable<Type> GetLoadableTypes(this Assembly assembly)
{
    // TODO: Argument validation
    try
    {
        return assembly.GetTypes();
    }
    catch (ReflectionTypeLoadException e)
    {
        return e.Types.Where(t => t != null);
    }
}

आप अच्छी तरह से स्थानांतरित करने के लिए इच्छा हो सकती है returnपकड़ ब्लॉक से बाहर बयान - मैं बहुत हूँ यह वहाँ अपने आप को किया जा रहा है के लिए उत्सुक नहीं, लेकिन यह शायद है कम से कम कोड ...


2
धन्यवाद, यह एक समाधान प्रतीत होता है (और मैं सहमत हूं, यह एक स्वच्छ समाधान नहीं लगता है)।
M4N

4
इस समाधान में अभी भी समस्याएँ हैं जब आप अपवाद में उजागर प्रकारों की सूची का उपयोग करने का प्रयास करते हैं। जो भी प्रकार लोड अपवाद का कारण है, FileNotFound, BadImage, आदि, अभी भी हर प्रकार के मुद्दे पर पहुंच वाले प्रकारों पर फेंक देंगे।
स्वीटफा

@sweetfa: हां, यह बहुत सीमित है - लेकिन अगर ओपी को केवल नाम खोजने की जरूरत है, उदाहरण के लिए, यह ठीक होना चाहिए।
जॉन स्कीट

1
मजेदार, इस पोस्ट को यहाँ उद्धृत किया गया है, काफी दिलचस्प: haacked.com/archive/2012/07/23/…
anhoppe

@sweetfa यह है कि मैं लौटे प्रकारों पर FileNotFound अपवाद की समस्या से बचने के लिए क्या करता हूं : From t As Type In e.Types Where (t IsNot Nothing) AndAlso (t.TypeInitializer IsNot Nothing)यह बहुत अच्छा काम करता है।
इलेक्ट्रोस्टूडिओस

22

जबकि ऐसा प्रतीत होता है कि कुछ बिंदु पर ReflectionTypeLoadException प्राप्त किए बिना कुछ भी नहीं किया जा सकता है, ऊपर दिए गए उत्तर सीमित हैं कि अपवाद से प्रदान किए गए प्रकारों का उपयोग करने का कोई भी प्रयास अभी भी मूल मुद्दे के साथ समस्या देगा जो कि लोड करने में विफल होने के कारण होता है।

इसे दूर करने के लिए निम्नलिखित कोड विधानसभा के भीतर स्थित लोगों तक सीमित है और विधेय को प्रकारों की सूची को और सीमित करने की अनुमति देता है।

    /// <summary>
    /// Get the types within the assembly that match the predicate.
    /// <para>for example, to get all types within a namespace</para>
    /// <para>    typeof(SomeClassInAssemblyYouWant).Assembly.GetMatchingTypesInAssembly(item => "MyNamespace".Equals(item.Namespace))</para>
    /// </summary>
    /// <param name="assembly">The assembly to search</param>
    /// <param name="predicate">The predicate query to match against</param>
    /// <returns>The collection of types within the assembly that match the predicate</returns>
    public static ICollection<Type> GetMatchingTypesInAssembly(this Assembly assembly, Predicate<Type> predicate)
    {
        ICollection<Type> types = new List<Type>();
        try
        {
            types = assembly.GetTypes().Where(i => i != null && predicate(i) && i.Assembly == assembly).ToList();
        }
        catch (ReflectionTypeLoadException ex)
        {
            foreach (Type theType in ex.Types)
            {
                try
                {
                    if (theType != null && predicate(theType) && theType.Assembly == assembly)
                        types.Add(theType);
                }
                // This exception list is not exhaustive, modify to suit any reasons
                // you find for failure to parse a single assembly
                catch (BadImageFormatException)
                {
                    // Type not in this assembly - reference to elsewhere ignored
                }
            }
        }
        return types;
    }

4

क्या आपने विधानसभा पर विचार किया है । यह देखते हुए कि आप क्या करने की कोशिश कर रहे हैं, यह पर्याप्त हो सकता है।


2
हां मैंने ऐसा माना था। लेकिन मैंने इसका उपयोग नहीं किया क्योंकि अन्यथा मुझे किसी भी निर्भरता को मैन्युअल रूप से लोड करना होगा। इसके अलावा कोड ReflectionOnlyLoad के साथ निष्पादन योग्य नहीं होगा (आपके द्वारा लिंक किए गए पृष्ठ पर रिमार्क्स अनुभाग देखें)।
M4N

3

मेरे मामले में, एप्लिकेशन फ़ोल्डर में अवांछित असेंबलियों की उपस्थिति के कारण भी यही समस्या थी। बिन फ़ोल्डर को खाली करने और एप्लिकेशन को फिर से बनाने का प्रयास करें।

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.