2014-04-30 33 views
2

我目前正在編寫一個應用程序套件,該插件系統使用MEF框架在運行時加載插件。使用MEF加載帶有嵌入式庫的DLL

我目前設置了一個頂級WPF應用程序,將其引用的DLL嵌入爲嵌入式資源,並在運行時使用描述的方法加載它們here

這工作正常,我得到我的單個文件WPF應用程序運行良好。

但是,我的另一個頂級控制檯應用程序使用MEF框架在運行時加載插件(WPF應用程序已修復並明確包含插件)。我的插件本身在各種庫上都有一些依賴關係,而控制檯應用程序從其中加載插件的擴展文件夾中散佈着各種庫DLL。

我想嵌入每個插件的依賴關係,使我的擴展目錄只包含頂級DLL文件。我上面使用的方法不適合這種方法,因爲插件組件找不到所需的依賴項,因爲它只是正在搜索這些嵌入式資源的執行程序集。

我目前OnResolveAssembly方法是這樣的:

public static Assembly OnResolveAssembly(object sender, ResolveEventArgs args) 
{ 
    Assembly executingAssembly = Assembly.GetExecutingAssembly(); 
    var assemblyName = new AssemblyName(args.Name); 

    string path = assemblyName.Name + ".dll"; 
    if (assemblyName.CultureInfo.Equals(CultureInfo.InvariantCulture) == false) 
    { 
     path = String.Format(@"{0}\{1}", assemblyName.CultureInfo, path); 
    } 

    using (Stream stream = executingAssembly.GetManifestResourceStream(path)) 
    { 
     if (stream == null) 
      return null; 

     var assemblyRawBytes = new byte[stream.Length]; 
     stream.Read(assemblyRawBytes, 0, assemblyRawBytes.Length); 

     return Assembly.Load(assemblyRawBytes); 
    } 
} 

我在想,則最好的辦法是在功能添加到跟蹤列表中加載的所有組件,一旦一個新的裝配已經以這種方式加載,遞歸地執行相同的操作;隨身攜帶任何嵌入式DLL。然後,您可以將這些DLL添加到充當緩存的列表中。

有沒有更好的方法來處理這個問題?

回答

2

我已經爲你實現了一個非常類似的解決方案,它對我來說工作得很好。正如你所看到的,我跟蹤_references字典中已經加載的程序集。

在我的情況下,我不需要「急切地」以任何遞歸方式加載所有嵌入式依賴關係,而是我的嵌入式程序集根據需要自行註冊應用程序主機。

public static class ApplicationHost 
{ 
    private static readonly Dictionary<string, Assembly> _references = new Dictionary<string, Assembly>(); 

    [STAThread] 
    private static void Main() 
    { 
     AppDomain.CurrentDomain.AssemblyResolve += (sender, args) => _references.ContainsKey(args.Name) ? _references[args.Name] : null; 
     RegisterAssemblyAndEmbeddedDependencies(); 
     // continue application bootstrapping... 
    } 

    public static void RegisterAssemblyAndEmbeddedDependencies() 
    { 
     var assembly = Assembly.GetCallingAssembly(); 
     _references[assembly.FullName] = assembly; 
     foreach (var resourceName in assembly.GetManifestResourceNames()) 
     { 
      using (var resourceStream = assembly.GetManifestResourceStream(resourceName)) 
      { 
       var rawAssembly = new byte[resourceStream.Length]; 
       resourceStream.Read(rawAssembly, 0, rawAssembly.Length); 
       var reference = Assembly.Load(rawAssembly); 
       _references[reference.FullName] = reference; 
      } 
     } 
    } 
} 
+0

您可以詳細說明嵌入式依賴關係如何註冊自己嗎?我試圖考慮這將如何工作,並且無法確定訂閱AssemblyResolve事件的位置。 – EdSalter