development

유형의 모든 파생 유형 가져 오기

big-blog 2021. 1. 7. 20:34
반응형

유형의 모든 파생 유형 가져 오기


유형의 모든 파생 유형을 찾는 더 나은 (더 성능이 높거나 더 좋은 코드) 방법이 있습니까? 현재 다음과 같은 것을 사용하고 있습니다.

  1. 중고 어셈블리의 모든 유형 가져 오기
  2. 'IsAssignable'이면 모든 유형으로 내 유형을 확인하십시오.

이 작업을 수행하는 더 좋은 방법이 있는지 궁금합니다.


나는 한 번 기본 B 형에서 상속 모든 유형을 얻기 위해이 Linq에-방법을 사용 :

    var listOfBs = (from domainAssembly in AppDomain.CurrentDomain.GetAssemblies()
                    from assemblyType in domainAssembly.GetTypes()
                    where typeof(B).IsAssignableFrom(assemblyType)
                    select assemblyType).ToArray();

편집 : 이것은 여전히 ​​더 많은 담당자를 얻는 것처럼 보이기 때문에 (더 많은 조회수) 더 많은 세부 정보를 추가하겠습니다.

  • 위에서 언급 한 링크에서 알 수 있듯이이 메서드는 각 호출에서 Reflection을 사용합니다. 따라서 동일한 유형에 대해 메서드를 반복적으로 사용할 때 한 번로드하면 훨씬 더 효율적으로 만들 수 있습니다.
  • Anton이 제안 했듯이 domainAssembly.GetExportedTypes()공개적으로 표시되는 유형 만 검색 하는 데 사용하여 (마이크로) 최적화 할 수 있습니다 (필요한 경우).
  • Noldorin이 언급 했듯이 Type.IsAssignable원본 (비 파생) 유형도 가져옵니다. ( 작동하지 Type.IsSubclassOf않지만 Type.IsSubclassOf기본 유형이 인터페이스 인 경우 작동하지 않습니다.)
  • '진짜'클래스를 확인하고 싶거나 필요로 할 수 있습니다 : && ! assemblyType.IsAbstract. (모든 인터페이스는 추상적 인 것으로 간주됩니다 . MSDN 참조 )

나는 당신이 제안한 방법이 모든 파생 유형을 찾는 더 쉬운 방법이 될 것이라고 확신합니다. 부모 클래스는 하위 클래스가 무엇인지에 대한 정보를 저장하지 않습니다 (그렇게한다면 상당히 어리석은 일입니다). 즉, 여기에서 모든 유형을 검색하는 것을 피할 수 없습니다.

유일한 권장 사항은 특정 유형이 다른 유형에서 파생되었는지 확인하기 위해 Type.IsSubclassOf대신 방법 을 사용하는 것입니다 Type.IsAssignable. 그래도 사용해야하는 이유가있을 수 있습니다 Type.IsAssignable(예 : 인터페이스에서 작동).


이 상황에서 얻을 수있는 유일한 최적화는 Assembly.GetExportedTypes()공개적으로 표시되는 유형 만 검색하는 데 사용 하는 것입니다. 그 외에는 속도를 높일 수있는 방법이 없습니다. LINQ는 가독성 측면에서 도움이 될 수 있지만 성능 측면에서는 도움이되지 않습니다.

IsAssignableFromReflector에 따르면, 문제의 유형이 필수 "클래스"인지 여부를 먼저 테스트 하여 불필요한 호출을 방지하기 위해 단락을 수행 할 수 있습니다 . 즉, 클래스 만 검색하고 "할당 가능성"에 대해 열거 형이나 배열을 테스트 할 필요가 없습니다.


더 나은 방법이나 직접적인 방법은 없다고 생각합니다.

더 나은 : 사용 IsSubclassOf대신에 IsAssignable.


baseType에 확인하려는 System.Type 객체가 포함되어 있고 matchType에 현재 반복 유형 (foreach-loop 등을 통해)의 System.Type 객체가 포함되어 있다고 가정합니다.

밀의 matchType이 baseType으로 표시된 클래스에서 파생되었는지 확인하려면

matchType.IsSubclassOf(baseType)

그리고 당신이 밀가루 matchType이 baseType으로 표현되는 인터페이스를 구현하는지 확인하고 싶다면

matchType.GetInterface(baseType.ToString(), false) != null

물론 baseType.ToString ()을 전역 변수로 저장하므로 항상 호출 할 필요가 없습니다. 유형이 많은 컨텍스트에서 필요할 수 있으므로 System.Threading.Tasks.Parallel.ForEach-Loop을 사용하여 모든 유형을 반복 할 수도 있습니다.


검색에만 관심이있는 경우 .NET Reflector가이 작업을 수행 할 수 있습니다. 그러나 그것은 실제로 가능한 것이 아닙니다. 현재로드 된 어셈블리에있는 모든 유형을 원하십니까? 실행중인 어셈블리에서 참조하는 어셈블리? 유형 목록을 얻는 방법에는 여러 가지가 있으며, 설명 할 수있는 (그리고 옵션을 제공하는) 무언가를 작성하는 것은 상대적으로 낮은 이익과 함께 상당히 큰 비용이 될 것입니다.

무엇을하려고합니까? 그것을 달성하는 더 나은 (또는 적어도 더 효율적인) 방법이있을 것입니다.


시작시 파생 된 유형의 정적 사전을 만들고이를 사용하여 조회하면됩니다. 예 : public static Dictionay<Type, Type[]> DerivedTypes { get;set; }여기서 Type은 검색에 포함 할 모든 유형이고 Type []은 파생 된 유형 목록입니다. 앱이 시작될 때 사전을 채우고 앱의 전체 수명 동안 사용하십시오.


나는 최고 답변이 준 코드를 사용했습니다. 유일한 것은 코드가 더 읽기 쉽기를 원했기 때문에 기본적으로 같은 것을 작성했지만 대신 다음과 같습니다.

var derived_types = new List<Type>();
foreach (var domain_assembly in AppDomain.CurrentDomain.GetAssemblies())
{
  var assembly_types = domain_assembly.GetTypes()
    .Where(type => type.IsSubclassOf(typeof(MyType)) && !type.IsAbstract);

  derived_types.AddRange(assembly_types);
}

필자의 경우 type.IsSubClassOf(MyType)위에서 언급 한 기본 클래스를 제외한 파생 유형 만 원했기 때문에 사용했습니다 . 또한 파생 된 유형이 추상 ( !type.IsAbstract)이 아니어야하므로 파생 된 추상 클래스도 제외합니다.

ReferenceURL : https://stackoverflow.com/questions/857705/get-all-derived-types-of-a-type

반응형