2013-05-04 7 views
8

플러그인을 사용하여 응용 프로그램을 만들려고합니다.FileNotFound 다른 도메인에 대한 종속성을로드 할 때 어셈블리

나는 MainLib.dll을 가지고 있는데, 여기에는 1 개의 방법으로 commnon 인터페이스 (ICommon)를 만들었습니다. 그런 다음 MainLib.dll에 대한 참조가있는 2 개의 .dll (플러그인)을 만들고 일부 클래스에서는 ICommon을 구현합니다. 또한이 .dlls exept System의 모든 참조를 제거했습니다.

그럼, .DLL의 유형 (그래서이 응용 프로그램은 또한 MainLib.dll에 참조) ICommon를 구현하는 경우 확인 newDomain 폴더에 ".\\Plugins"로드 모든 .dll을을 모니터링하는 응용 프로그램을 만들었습니다. 예이면 일부 목록에 .dll 이름을 추가하십시오.

그리고 지금 여기에 문제 : 내가 플러그인을로드하려고하기 전에 - 모든 플러그인이 .dll을의 의존성을 가지고 있기 때문에 내가 NEWDOMAIN에 MailLib.dll 및 시스템을로드합니다. 그들은 정확하게 올린다. 그럼,이 플러그인을로드하기 시작하고, 여기에 내가있다 :

FileNotFoundException이, 파일이나 어셈블리를로드 할 수 없습니다 ', 버전 = 1.0.0.0을 PluginWithException을, PublicKeyToken = null의 문화 = 중립'또는 해당 종속성 중 하나. 시스템이 지정된 파일을 찾을 수 없습니다.) string assembly LoadAssembly = domain.Load (Assembly.LoadFrom (asm) .FullName);

PluginWithException 어셈블리에는 System 및 MainLib의 종속성 만 2 개 있습니다. PluginWithException을로드하기 위해 tryied하기 전에 새 도메인에서 어셈블리를 검사 한 결과 시스템 및 MainLib이이 도메인에로드되었습니다. 그래서 나는 의존성이있는 어떤 경계선을 볼 수 없다. 나는 this 주제를 읽고 ProxyDomain와 함께 솔루션을 시도했지만 예외는 동일합니다.

내가 뭘 잘못하고있어? 여기

코드 : 당신이 어셈블리를로드하는 이유

그러나 AppDomain domain = AppDomain.CreateDomain("tmpDomain", null, new AppDomainSetup { ApplicationBase = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "Plugins") });

, 내가 볼 수 없습니다 :

public static List<string> SearchPlugins(string[] names) 
{ 
    AppDomain domain = AppDomain.CreateDomain("tmpDomain"); 
    domain.Load(Assembly.LoadFrom(@".\MainLib.dll").FullName); 
    domain.Load(@"System, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"); 
    MessageBox.Show(GetAssembies(domain)); // here I can see that System and MailLib exist in new domain 

    List<string> plugins = new List<string>(); 

    foreach (string asm in names) 
    { 
     Assembly loadedAssembly = domain.Load(Assembly.LoadFrom(asm).FullName); // here I have exception 

     var theClassTypes = from t in loadedAssembly.GetTypes() 
          where t.IsClass && 
            (t.GetInterface("ICommonInterface") != null) 
          select t; 
     if (theClassTypes.Count() > 0) 
     { 
      plugins.Add(asm); 
     } 
    } 
    AppDomain.Unload(domain); 
    return plugins; 
} 

답변

6

당신은 AppDomains에 대한 검색 경로를 어떻게 설정하는지 지정하지 않으므로 플러그인 디렉토리에서 DLL을 찾을 수 있습니다.하지만 어제 답변 한 것과 비슷한 문제가 발생할 수 있습니다.

AppDomain.Load() fails with FileNotFoundException

아마도 이것은 또한 문제를 해결할 것인가? 어떻게 지내는지 알려줘.

+0

감사합니다. 당신의 대답은 매우 유용합니다! app.config가 포함 된 솔루션이 작동하지만 가장 좋은 방법은 아닙니다. 나는 로더와 함께 해결책을 시도했다. 'var plugins = loader.LoadPlugins ( Assembly.LoadFrom (Environment.CurrentDirectory + @ "\ Plugins \ PluginWithOutException.dll"). FullName);'그러나 도움이되지 않았다. (예외는 동일합니다 : ( –

+1

자식 AppDomain을 생성 할 때 PrivateBinPath를 설정하려고 했으므로 어셈블리의 Plugins 폴더를 볼 수 있습니까? 'var appDomainSetup = new AppDomainSetup {PrivateBinPath = "Plugins"}; var domain = AppDomain.CreateDomain ("tmpDomain", AppDomain.CurrentDomain.Evidence, appDomainSetup); –

+0

감사합니다! 이전에'PrivateBinPath'를 사용하여 솔루션을 시도했지만 잘못 했으므로 이제는 제대로로드되고 작동합니다. 어셈블리를 새 도메인에로드하고, 인터페이스의 메소드를 호출하고, 도메인을 언로드하고, 현재 (기본) 도메인에서 어셈블리를 검사했습니다. 불행히도 현재 (d 오류) 도메인. 또한 Loader가없는 app.config를 사용하는 솔루션은 기본 도메인에 어셈블리를로드합니다. 기본 도메인에이 어셈블리를로드하지 않는 것이 실제로 가능합니까? –

2

당신은에서 어셈블리를로드하는 경우 도메인을 이야기 할 수 있습니다 현재 (기본) 도메인 및 tmpDomain.

+1

감사합니다. 코드를 사용해 보았지만 예외는 동일합니다. 내 도메인에 어셈블리를로드하지 않기 때문에 응용 프로그램에 이미지를 저장하지 않으려 고합니다. (이미지가 100 개 이상인 경우), 일부 플러그인을로드하여 사용하고 응용 프로그램에서 버릴 수 있습니다. 나는 그것을 필요로하지 않는다. –

+1

OK -하지만 Assembly.LoadFrom (asm)을 실행하면 현재 도메인에로드됩니다. 이것은 당신의 목적을 이깁니다. 'PluginLoader' 커스텀 클래스를 가지고 그 클래스를 tmpDomain에로드하는 것이 좋습니다. 그런 다음 해당 클래스에 코드를 작성하여 'Assembly.LoadFrom'을 사용하여 모든 플러그인을로드하고 원하는 플러그인 목록을 반환 할 수 있습니다. – YK1

+0

sysinternals 프로세스 탐색기 사용 - 언제 어떤 도메인에로드되는지 확인할 수 있습니다. – YK1