2010-04-17 4 views
12

Assembly.Loadfrom을 사용하여 응용 프로그램과로드 플러그인 어셈블리에 대한 플러그인 프레임 워크를 구현합니다. 그런 다음 GetTypes()를 사용하여 지원되는 인터페이스의 각 플러그인 파일 유형을 자세히 검사합니다.Assembly.GetTypes() - ReflectionTypeLoadException

플러그인에 대한 경로가 사용자에 의해 제공되며 폴더의 각 파일을 순환하여 플러그인 (플러그인)이 플러그인 인터페이스를 지원하는지 확인합니다. 그렇다면 인스턴스를 만들고, 그렇지 않으면 다음 파일로 이동합니다.

하나의 코드베이스 (appA_1 및 appA_2)에서 두 가지 버전의 소프트웨어를 빌드합니다.

플러그인을로드하면 플러그인 파일과 동시에 빌드 된 응용 프로그램에서 플러그인을로드 할 때 잘 작동합니다. 그러나 appA_2를 빌드하고 appA_1의 플러그인 폴더를 가리키면 GetTypes()가 호출 될 때 예외가 발생합니다.

코드의 기본 버전은 다음과 같습니다.

var pluginAssembly = Assembly.LoadFrom(FileName);  
foreach (var pluginType in pluginAssembly.GetTypes()) 
{ 

"ReflectionTypeLoadException"예외가 발생합니다.

이것은 응용 프로그램이 모든 사람이 작성한 플러그인 유형을로드 할 수 있기를 원하는 경우에 관한 것입니다. 우리가 누락 된 것이 있습니까?

편집 : LoaderExceptions를 통해 반복 한 결과 System.IO.FileNotFoundException 예외를 생성하는 단일 파일 libPublic.dll이 있음을 발견했습니다. 이상하게도이 파일은 응용 프로그램 디렉토리에 있고 플러그인은 프로젝트 파일을 참조합니다.

는 편집 2 : 우리는 다음 찾을 예외 로그에서 "어셈블리 이름 비교는 불일치 결과 : 개정 번호"

+0

예외 메시지는 무엇입니까? 예외에 내부 예외가 있습니까? 그게 무슨 메시지 야? – dtb

+0

MEF와 같은 기존 프레임 워크를 사용하지 않는 이유가 무엇입니까? – dtb

+0

MEF를 사용할 때 여전히 이와 같은 문제를 만들 수 있습니다. MEF는 쓸데없는 작업을 처리하는 데 확실히 유용합니다. –

답변

14

몇 가지 :

  • 을 확인 당신은 돈 ' 플러그인 디렉토리 (예 : 이미 메인 디렉토리에있는 응용 프로그램 디렉토리에서로드중인 어셈블리)에 중복 어셈블리가 있습니다. 그렇지 않으면 플러그인을로드 할 때 동일한 어셈블리의 추가 사본이로드 될 수 있습니다. 이것은 재미 예외로 이어질 수 있습니다 :

    'MyObject'유형의 개체는 'MyObject'유형이 아닙니다. 유형을 인스턴스화 할 때 예외를 받고있는 경우

  • , 당신은 AppDomain.AssemblyResolve을 처리해야 할 수 있습니다

    private void App_Startup(object sender, StartupEventArgs e) 
    { 
        // Since we'll be dynamically loading assemblies at runtime, 
        // we need to add an appropriate resolution path 
        // Otherwise weird things like failing to instantiate TypeConverters will happen 
        AppDomain.CurrentDomain.AssemblyResolve += CurrentDomain_AssemblyResolve; 
    } 
    
    private Assembly CurrentDomain_AssemblyResolve(object sender, ResolveEventArgs args) 
    { 
        var domain = (AppDomain) sender; 
    
        foreach (var assembly in domain.GetAssemblies()) 
        { 
         if (assembly.FullName == args.Name) 
         { 
          return assembly; 
         } 
        } 
    
        return null; 
    } 
    

을 나는 그것이 CLR에게 가지고 조금 이상하다 실현하는, 어셈블리를 해결하려면 해결하기 위해 사용하고있는 이름을 가진 어셈블리를 찾으십시오.하지만이 어셈블리가 없으면 이상한 일이 발생하는 것을 보았습니다. 예를 들어 플러그인 어셈블리에서 유형을 인스턴스화 할 수 있지만 TypeDescriptor.GetConverter을 사용하려고하면 클래스에 Converter 속성을 볼 수는 있지만 클래스에 대해 TypeConverter을 찾지 못합니다.당신이 당신의 플러그인으로 작업 할 때 나중에 이러한 문제로 실행할 수 있지만


편집을 보면, 이것은 아마 당신의 현재 예외의 원인없는 것입니다.

+1

넌 대단해! 중복 어셈블리 문제가있어서이 답변으로 저를 구해 줬습니다! – JoeCool

+0

이것으로 내 문제도 해결되었습니다. 사용자 정의 UITypeEditor 및 TypeConverters를 노출 한 플러그인을로드하는 중일 때, 유형이로드되는 동안 편집자/변환기가 인스턴스화되지 않습니다. 또한 내 플러그인은 응용 프로그램과 관련된 하위 디렉토리에 있으며 기껏해야 호스트 응용 프로그램과 동일한 디렉토리에 플러그인을 넣으면 이상하게 작동합니다. 이 솔루션은 위치에 관계없이 플러그인을 작동시키는 데 도움이됩니다. – Mike

+0

당신은 틀린 품목입니다. 부모 응용 프로그램에 이미있는 자식 응용 프로그램의 어셈블리를로드하는 중입니다. AppDomain.CurrentDomain.GetAssemblies()를로드 할 때 어셈블리를 가져 와서 GetTypes()에서 Loader 문제를 해결했습니다. 고마워요 :) @Dan Dryant –

0

어셈블리 버전이 일치하지 않습니다. 귀하의 플러그인이이 libPublic.dll을 참조하기 때문에 신중하게 버전을 변경해야하며, 특히 리비전/빌드/등을 부풀리지 않아야합니다. 모든 컴파일시 숫자.

2

이 게시물 덕분에 에 들어있는 ReflectionTypeLoadException을 해결할 수있었습니다. 디자이너 어셈블리 (디자인 타임에 사용되는 winforms 스마트 태그)는 사용자 지정 클래스 라이브러리의 일부 형식을 검색합니다.

/// <summary> 
/// Get the types defined in the RootComponent. 
/// </summary> 
private List<Type> getAssemblyTypes(IServiceProvider provider) 
{ 
    var types = new List<Type>(); 
    try 
    { 
     IDesignerHost host = (IDesignerHost)provider.GetService(typeof(IDesignerHost)); 
     ITypeResolutionService resolution = (ITypeResolutionService)provider.GetService(typeof(ITypeResolutionService)); 
     AppDomain.CurrentDomain.AssemblyResolve += (sender, args) => 
     { 
      foreach (var assembly in ((AppDomain)sender).GetAssemblies()) 
      { 
       if (assembly.FullName == args.Name) 
       { 
        return assembly; 
       } 
      } 

      return null; 
     }; 

     Type rootComponentType = resolution.GetType(host.RootComponentClassName, false); 
     types = rootComponentType.Assembly.GetTypes().ToList(); 
    } 
    catch 
    { 
    } 

    return types; 
} 
+0

IServiceProvider는 어디에서 왔습니까? 그것을 어떻게 얻을 수 있습니까? – Pangamma

관련 문제