वर्तमान में भरी हुई विधानसभाओं के माध्यम से आप कैसे लूप करते हैं?


120

मुझे अपने ASP.NET एप्लिकेशन में एक "डायग्नोस्टिक्स" पेज मिला है, जो डेटाबेस कनेक्शन (सों) को सत्यापित करने, वर्तमान ऐपसेटिंग और कनेक्शनस्ट्रीम, इत्यादि को सत्यापित करने जैसे काम करता है। इस पेज का एक सेक्शन महत्वपूर्ण प्रकारों के असेंबली संस्करणों को प्रदर्शित करता है। , लेकिन मैं यह पता नहीं लगा सका कि प्रभावी रूप से सभी भरी हुई विधानसभाओं के संस्करणों को कैसे दिखाया जाए।

.NET अनुप्रयोग में वर्तमान में संदर्भित और / या भरी हुई असेंबली का पता लगाने का सबसे प्रभावी तरीका क्या है ?

नोट: मैं फ़ाइल-आधारित विधियों में दिलचस्पी नहीं ले रहा हूं, जैसे कि किसी विशेष निर्देशिका में * .dll के माध्यम से पुनरावृत्ति करना। मुझे इस बात में दिलचस्पी है कि आवेदन वास्तव में अभी क्या उपयोग कर रहा है

जवाबों:


24

यह विस्तार विधि सभी संदर्भित विधानसभाओं, पुनरावर्ती, नेस्टेड असेंबली सहित प्राप्त करता है।

जैसा कि यह उपयोग करता है ReflectionOnlyLoad, यह एक अलग AppDomain में असेंबलियों को लोड करता है , जिसमें JIT प्रक्रिया में हस्तक्षेप न करने का लाभ होता है।

आप देखेंगे कि वहाँ भी है MyGetMissingAssembliesRecursive। आप किसी भी अनुपलब्ध असेंबली का पता लगाने के लिए इसका उपयोग कर सकते हैं, लेकिन किसी कारण से वर्तमान निर्देशिका में मौजूद नहीं है। MEF का उपयोग करते समय यह अविश्वसनीय रूप से उपयोगी है । वापसी सूची आपको गुमशुदा असेंबली दोनों देगी, और जो इसका मालिक है (इसके माता-पिता)।

/// <summary>
///     Intent: Get referenced assemblies, either recursively or flat. Not thread safe, if running in a multi
///     threaded environment must use locks.
/// </summary>
public static class GetReferencedAssemblies
{
    static void Demo()
    {
        var referencedAssemblies = Assembly.GetEntryAssembly().MyGetReferencedAssembliesRecursive();
        var missingAssemblies = Assembly.GetEntryAssembly().MyGetMissingAssembliesRecursive();
        // Can use this within a class.
        //var referencedAssemblies = this.MyGetReferencedAssembliesRecursive();
    }

    public class MissingAssembly
    {
        public MissingAssembly(string missingAssemblyName, string missingAssemblyNameParent)
        {
            MissingAssemblyName = missingAssemblyName;
            MissingAssemblyNameParent = missingAssemblyNameParent;
        }

        public string MissingAssemblyName { get; set; }
        public string MissingAssemblyNameParent { get; set; }
    }

    private static Dictionary<string, Assembly> _dependentAssemblyList;
    private static List<MissingAssembly> _missingAssemblyList;

    /// <summary>
    ///     Intent: Get assemblies referenced by entry assembly. Not recursive.
    /// </summary>
    public static List<string> MyGetReferencedAssembliesFlat(this Type type)
    {
        var results = type.Assembly.GetReferencedAssemblies();
        return results.Select(o => o.FullName).OrderBy(o => o).ToList();
    }

    /// <summary>
    ///     Intent: Get assemblies currently dependent on entry assembly. Recursive.
    /// </summary>
    public static Dictionary<string, Assembly> MyGetReferencedAssembliesRecursive(this Assembly assembly)
    {
        _dependentAssemblyList = new Dictionary<string, Assembly>();
        _missingAssemblyList = new List<MissingAssembly>();

        InternalGetDependentAssembliesRecursive(assembly);

        // Only include assemblies that we wrote ourselves (ignore ones from GAC).
        var keysToRemove = _dependentAssemblyList.Values.Where(
            o => o.GlobalAssemblyCache == true).ToList();

        foreach (var k in keysToRemove)
        {
            _dependentAssemblyList.Remove(k.FullName.MyToName());
        }

        return _dependentAssemblyList;
    }

    /// <summary>
    ///     Intent: Get missing assemblies.
    /// </summary>
    public static List<MissingAssembly> MyGetMissingAssembliesRecursive(this Assembly assembly)
    {
        _dependentAssemblyList = new Dictionary<string, Assembly>();
        _missingAssemblyList = new List<MissingAssembly>();
        InternalGetDependentAssembliesRecursive(assembly);

        return _missingAssemblyList;
    }

    /// <summary>
    ///     Intent: Internal recursive class to get all dependent assemblies, and all dependent assemblies of
    ///     dependent assemblies, etc.
    /// </summary>
    private static void InternalGetDependentAssembliesRecursive(Assembly assembly)
    {
        // Load assemblies with newest versions first. Omitting the ordering results in false positives on
        // _missingAssemblyList.
        var referencedAssemblies = assembly.GetReferencedAssemblies()
            .OrderByDescending(o => o.Version);

        foreach (var r in referencedAssemblies)
        {
            if (String.IsNullOrEmpty(assembly.FullName))
            {
                continue;
            }

            if (_dependentAssemblyList.ContainsKey(r.FullName.MyToName()) == false)
            {
                try
                {
                    var a = Assembly.ReflectionOnlyLoad(r.FullName);
                    _dependentAssemblyList[a.FullName.MyToName()] = a;
                    InternalGetDependentAssembliesRecursive(a);
                }
                catch (Exception ex)
                {
                    _missingAssemblyList.Add(new MissingAssembly(r.FullName.Split(',')[0], assembly.FullName.MyToName()));
                }
            }
        }
    }

    private static string MyToName(this string fullName)
    {
        return fullName.Split(',')[0];
    }
}

अपडेट करें

इस कोड थ्रेड को सुरक्षित बनाने के लिए, lockइसे चारों ओर लगाएं। यह वर्तमान में डिफ़ॉल्ट रूप से थ्रेड सुरक्षित नहीं है, क्योंकि यह अपने जादू करने के लिए एक साझा स्थिर वैश्विक चर का संदर्भ देता है।


मैं बस इसे थ्रेड सेफ़ होने के लिए फिर से लिखता हूं, इसलिए इसे कई अलग-अलग थ्रेड्स से एक साथ बुलाया जा सकता है (यह सुनिश्चित नहीं है कि आप ऐसा क्यों चाहते हैं, लेकिन हे, इसके सुरक्षित)। मुझे बताएं कि क्या आप चाहते हैं कि मैं कोड पोस्ट करूं।
कंटंगा

2
@Contango क्या आप अपने थ्रेड सुरक्षित संस्करण को पोस्ट कर सकते हैं, या यदि आपने इसके बारे में ब्लॉग लिखा है, तो पोस्ट करें?
रॉबर्ट

2
इस धागे को सुरक्षित बनाने का भोला तरीका lockपूरी चीज़ के चारों ओर लगाना है। दूसरी विधि जिसे मैंने वैश्विक स्थिर "_dependentAssemblyList" पर निर्भरता को समाप्त कर दिया था, इसलिए यह बिना किसी आवश्यकता के थ्रेड सुरक्षित हो जाता है lock, जिसमें कुछ छोटी गति के फायदे हैं यदि कई थ्रेड्स एक साथ यह निर्धारित करने की कोशिश कर रहे हैं कि असेंबली गायब हैं (यह थोड़ा सा है एक कोने का मामला)।
कंटैंगो

3
जोड़ना lock"थ्रेड सेफ" के रास्ते में बहुत कुछ जोड़ने वाला नहीं है। यकीन है, कि कोड के उस ब्लॉक को एक बार में केवल एक ही निष्पादित करता है; लेकिन अन्य धागे असेंबली को किसी भी समय लोड कर सकते हैं जो उन्हें पसंद है और जो कुछ foreachछोरों के साथ समस्याएं पैदा कर सकता है ।
पीटर रिची

1
@Peter Ritchie एक साझा स्टेटिक ग्लोबल वैरिएबल है जो रिकर्सन के दौरान उपयोग किया जाता है, इसलिए उस तक सभी एक्सेस के चारों ओर एक लॉक जोड़ने से वह हिस्सा थ्रेड सुरक्षित हो जाएगा। यह सिर्फ अच्छा प्रोग्रामिंग अभ्यास है। आमतौर पर सभी आवश्यक विधानसभाओं को स्टार्टअप पर लोड किया जाता है, जब तक कि एमईएफ जैसी किसी चीज का उपयोग नहीं किया जाता है, इसलिए थ्रेड सुरक्षा वास्तव में एक मुद्दा नहीं है।
कंटैंगो

193

वर्तमान के लिए लोड हो रही असेंबली AppDomain:

var loadedAssemblies = AppDomain.CurrentDomain.GetAssemblies();

विधानसभाओं को दूसरी विधानसभा द्वारा संदर्भित करना:

var referencedAssemblies = someAssembly.GetReferencedAssemblies();

ध्यान दें कि यदि असेंबली A को असेंबली B और असेंबली A को लोड किया जाता है, तो इसका अर्थ यह नहीं है कि असेंबली B भी भरी हुई है। असेंबली बी को केवल तभी लोड किया जाएगा जब और जब जरूरत होगी। उस कारण से, उदाहरणों के बजाय उदाहरणों को GetReferencedAssemblies()लौटाता है ।AssemblyNameAssembly


2
वैसे मुझे कुछ इस तरह की आवश्यकता है - एक .net समाधान जिसे मैं सभी परियोजनाओं में सभी संदर्भित विधानसभाओं का पता लगाना चाहता हूं। विचार?
कुमार वैभव

कृपया ध्यान दें कि दोनों विधियाँ केवल डीएल की सूची बनाती हैं जो वास्तव में उपयोग की जाती हैं। स्पष्ट रूप से इसका कोई मतलब नहीं है कि उपयोग किए जाने वाले समाधानों में संदर्भ नहीं हैं, लेकिन यह भ्रमित हो सकता है जब कोई सभी विधानसभाओं के माध्यम से सट्टा स्कैन करने की कोशिश कर रहा हो। सभी विधानसभाएं सिर्फ दिखावे के लिए नहीं हो सकती हैं।
पोम्पायर

3
ओपी वर्तमान में भरी हुई विधानसभाओं को संदर्भित विधानसभाओं से नहीं पूछता है । यह सवाल का जवाब देता है। ठीक वही जो मेरे द्वारा खोजा जा रहा था।
19

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