IT

Assembly.GetTypes () 호출시 ReflectionTypeLoadException을 방지하는 방법

lottoking 2020. 9. 1. 07:43
반응형

Assembly.GetTypes () 호출시 ReflectionTypeLoadException을 방지하는 방법


다음과 같은 코드를 사용하여 특정 인터페이스를 구현하는 형식에 대한 어셈블리를 스캔합니다.

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()입니다.

제 경우에는 문제를 예방할 수 없습니다. 검색중인 유형에는 사용할 수없는 어셈블리가 필요하지 않습니다.

문제는 예외를 발생시키는 발생 유형을 어떻게 처리 할 수 ​​있거나 무시할 수있는 어셈블리에 포함 된 다른 무시할 수 있습니까?


상당히 불쾌한 방법은 다음과 같다.

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성명을 잡으려고 할 수도 있습니다. 저도 거기에있는 것을 좋아하지 않는 것이 가장 짧은 코드 일 것 입니다 .


어느 시점에서 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;
    }

Assembly.ReflectionOnlyLoad 를 고려해 보 ? 당신이 원하는 일을 고려하면 충분할 수 있습니다.


제 경우에는 응용 프로그램 폴더에 원치 않는 어셈블리가 있기 때문에 동일한 문제가 발생했습니다. Bin 폴더를 지우고 응용 프로그램을 다시 빌드하십시오.

참고 URL : https://stackoverflow.com/questions/7889228/how-to-prevent-reflectiontypeloadexception-when-calling-assembly-gettypes

반응형