Programing

현재로드 된 어셈블리를 어떻게 반복합니까?

lottogame 2020. 7. 17. 08:14
반응형

현재로드 된 어셈블리를 어떻게 반복합니까?


ASP.NET 응용 프로그램에 데이터베이스 연결 확인, 현재 appSettings 및 ConnectionStrings 표시 등의 작업을 수행하는 "진단"페이지가 있습니다.이 페이지의 섹션에는 전체적으로 사용되는 중요한 유형의 어셈블리 버전이 표시됩니다. 그러나로드 된 모든 어셈블리의 버전을 효과적으로 표시하는 방법을 알 수 없었습니다.

.NET 응용 프로그램에서 현재 참조되거나로드 된 모든 어셈블리 를 파악하는 가장 효과적인 방법은 무엇입니까 ?

참고 : 특정 디렉토리에서 * .dll을 반복하는 것과 같은 파일 기반 방법에는 관심이 없습니다. 현재 응용 프로그램이 실제로 사용 하는 것에 관심이 있습니다.


이 확장 방법은 중첩 된 어셈블리를 포함하여 모든 참조 된 어셈블리를 재귀 적으로 가져옵니다.

는를 사용하므로 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주위에 두십시오. 마법을 수행하기 위해 공유 정적 전역 변수를 참조하기 때문에 현재 기본적으로 스레드 안전하지 않습니다.


현재의로드 된 어셈블리 가져 오기 AppDomain:

var loadedAssemblies = AppDomain.CurrentDomain.GetAssemblies();

Getting the assemblies referenced by another assembly:

var referencedAssemblies = someAssembly.GetReferencedAssemblies();

Note that if assembly A references assembly B and assembly A is loaded, that does not imply that assembly B is also loaded. Assembly B will only be loaded if and when it is needed. For that reason, GetReferencedAssemblies() returns AssemblyName instances rather than Assembly instances.

참고URL : https://stackoverflow.com/questions/383686/how-do-you-loop-through-currently-loaded-assemblies

반응형