আপনি বর্তমানে লোড হওয়া অ্যাসেমব্লির মাধ্যমে কীভাবে লুপ করবেন?


120

আমি আমার এএসপি.এনইটি অ্যাপ্লিকেশনটিতে একটি "ডায়াগনস্টিক্স" পৃষ্ঠা পেয়েছি যা ডাটাবেস সংযোগ (গুলি) যাচাই করা, বর্তমান অ্যাপসেটিংস এবং সংযোগসট্রিংস ইত্যাদির মতো কাজগুলি করে etc. , তবে আমি বোঝা গেলাম না যে কীভাবে লোড হওয়া অ্যাসেম্বলির সমস্ত সংস্করণ কার্যকরভাবে প্রদর্শন করতে পারি।

.NET অ্যাপ্লিকেশনে বর্তমানে সমস্ত রেফারেন্সড এবং / অথবা লোড হওয়া অ্যাসেম্বলিগুলি বের করার সর্বাধিক কার্যকর উপায় কী ?

দ্রষ্টব্য: আমি ফাইল-ভিত্তিক পদ্ধতিগুলিতে আগ্রহী নই, যেমন একটি নির্দিষ্ট ডিরেক্টরিতে * .dll এর মাধ্যমে পুনরাবৃত্তি করা। আমি এখনই অ্যাপ্লিকেশনটি আসলে কী ব্যবহার করছে তাতে আগ্রহী।

উত্তর:


24

এই এক্সটেনশন পদ্ধতিটি নেস্টেড অ্যাসেম্বলিগুলি সহ পুনরাবৃত্তভাবে সমস্ত রেফারেন্স অ্যাসেম্বলিসমূহ পায়।

এটি যেমন ব্যবহার করে ReflectionOnlyLoad, এটি পৃথক অ্যাপডোমাইনে সমাবেশগুলি লোড করে, এতে জেআইটি প্রক্রিয়াতে হস্তক্ষেপ না করার সুবিধা রয়েছে।

আপনি লক্ষ্য করতে পারেন যে একটি আছে 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
@ কনটাঙ্গো আপনি কি আপনার থ্রেড নিরাপদ সংস্করণ পোস্ট করতে পারেন, বা আপনি যদি এটি সম্পর্কে একটি ব্লগ লিখে থাকেন তবে তা পোস্ট করতে পারেন?
রবার্ট

2
এই থ্রেডটিকে নিরাপদ করার সহজ উপায় হ'ল lockপুরো জিনিসটিকে ঘিরে। আমি যে অন্য পদ্ধতিটি ব্যবহার করেছি বিশ্বব্যাপী স্থিতিশীল "_ depend dependAsorsesList" এর উপর নির্ভরশীলতা মুছে ফেলা হয়েছে, তাই এটি কোনও প্রয়োজন ছাড়াই থ্রেড নিরাপদ হয়ে যায় lock, একাধিক থ্রেড একই সাথে কী অ্যাসেমব্লিগুলি অনুপস্থিত রয়েছে তা নির্ধারণ করার চেষ্টা করা হয় (এটি কিছুটা একটি কোণার কেস)।
কনটাঙ্গো

3
একটি lockযোগ করা "থ্রেড নিরাপদ" এর পথে তেমন যোগ করতে পারে না। অবশ্যই, এটি সেই কোডের ব্লকটিকে একবারে কেবলমাত্র একটি কার্যকর করে; তবে অন্যান্য থ্রেডগুলি তারা যে কোনও সময় অ্যাসেম্বলিগুলি লোড করতে পারে এবং এটি কিছু foreachলুপগুলির সাথে সমস্যা সৃষ্টি করতে পারে ।
পিটার রিচি

1
@ পিটার রিচি এখানে একটি ভাগ করা স্থির গ্লোবাল ভেরিয়েবল রয়েছে যা পুনরাবৃত্তির সময় ব্যবহৃত হয়, সুতরাং এতে সমস্ত অ্যাক্সেসের চারপাশে একটি লক যুক্ত করা সেই অংশের থ্রেডটিকে নিরাপদ করে তুলবে। এটি কেবল ভাল প্রোগ্রামিং অনুশীলন। সাধারণত সমস্ত প্রয়োজনীয় সমাবেশগুলি স্টার্টআপে লোড হয়, যদি না এমইএফ এর মতো কিছু ব্যবহার করা হয়, সুতরাং থ্রেড সুরক্ষা বাস্তবে বাস্তবে কোনও সমস্যা নয়।
কনটাঙ্গো

193

বর্তমানের জন্য ভারী সমাবেশগুলি নেওয়া AppDomain:

var loadedAssemblies = AppDomain.CurrentDomain.GetAssemblies();

অন্য সংসদ দ্বারা রেফারেন্স করা সমাবেশ:

var referencedAssemblies = someAssembly.GetReferencedAssemblies();

নোট করুন যে বিধানসভা A এর বিধানসভা বি এবং বিধানসভা A লোড করা থাকলে, এটি বোঝায় না যে বিধানসভা বিও লোড হয়েছে। বিধানসভা বি কেবল তখনই লোড হবে যখন প্রয়োজন হবে। যে কারণে, দৃষ্টান্তগুলির চেয়ে উদাহরণগুলি GetReferencedAssemblies()ফেরত দেয় ।AssemblyNameAssembly


2
ওয়েল আমার এই জাতীয় কিছু দরকার - একটি নেট নেটওয়াকশন দিয়ে আমি সমস্ত প্রকল্পের সমস্ত রেফারেন্সড অ্যাসেম্বলিগুলি খুঁজে পেতে চাই। ধারনা?
কুমার বৈভব

দয়া করে মনে রাখবেন যে উভয় পদ্ধতিই কেবলমাত্র ব্যবহৃত ডেলগুলির তালিকা করে। স্পষ্টতই যে সমাধানগুলিতে ব্যবহৃত হয় না সেগুলির রেফারেন্স পাওয়া কোনও অর্থবোধ করে না, তবে কেউ যখন সমস্ত অ্যাসেমব্লির মাধ্যমে অনুমানমূলকভাবে স্ক্যান করার চেষ্টা করছেন তখন এটি বিভ্রান্তিকর হতে পারে। সমস্ত সমাবেশগুলি কেবল প্রদর্শিত হবে না।
পোম্পায়ার

3
ওপি জিজ্ঞাসা করছে যে বর্তমানে লোড হওয়া অ্যাসেমব্লিকে রেফারেন্স অ্যাসেমসিলগুলি নয়। এই প্রশ্নের উত্তর। ঠিক আমি খুঁজছেন ছিল কি.
মাইকজানসেন

অনুষ্ঠানের জন্য বিধানসভা বি লোড হয় কখন?
কিকিনেট
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.