2013-12-16 107 views
0

我正在爲現有的C#.NET程序開發一個插件。它的結構方式是將您的自定義.dll文件放入程序根目錄/插件/您的​​插件名稱/您的插件名稱中.DLLc#類庫項目 - 從相同的文件夾加載DLL?

這一切運行良好,但現在我試圖在我的項目中使用NAudio 。

我已經通過Nuget下載NAudio,並且該部分工作正常,但問題在於它在程序根目錄中查找NAudio.dll,而不是在我的插件的文件夾中。

這使得很難分發我的插件,因爲除了將插件放入「插件」文件夾之外,它將依賴於用戶在其程序根目錄中放置NAudio.dll。

來源: SettingsView.xaml:

<Button HorizontalAlignment="Center" 
    Margin="0 5" 
    Width="120" 
    Command="{Binding SoundTestCommand, 
    Source={StaticResource SettingsViewModel}}" 
    Content="Sound Test" /> 

SettingsViewModel.cs:

using NAudio.Wave; 
. 
. 
. 
    public void SoundTest() 
    { 
     IWavePlayer waveOutDevice; 
     WaveStream mainOutputStream; 
     WaveChannel32 inputStream; 

     waveOutDevice = new WaveOut(); 

     mainOutputStream = new Mp3FileReader(@"E:\1.mp3"); 
     inputStream = new WaveChannel32(mainOutputStream); 

     inputStream.Volume = 0.2F; 

     waveOutDevice.Init(mainOutputStream); 
     waveOutDevice.Play(); 
    } 

我如何得到C#尋找n音訊在程序根/插件/我的插件名稱/ NAudio.dll,而不是在Program Root/NAudio.dll中查找它?

我使用VS Express 2013,目標框架是4.5,輸出類型是類庫。

編輯:

我發現2種方法,使這項工作(我不知道這兩種方法的優點和缺點是 - 如果有人知道我將不勝感激附加信息)。

  1. 使用NuGet包Costura.Fody

    安裝NuGet包後,我根本就設置的所有其他引用「複製本地」到「」,然後將「複製本地」爲n音訊爲「」。

    現在,當我編譯時,NAudio.dll被壓縮並添加到我自己的DLL中。

  2. 使用AssemblyResolver概述如下。

    它沒有工作的時候了,所以這裏是一些額外的信息,可以幫助任何人都面臨着同樣的問題:

    我把科裏的代碼,因爲他的貼吧到助手文件夾中。

    我的切入點是Plugin.cs,類爲public class Plugin : IPlugin, INotifyPropertyChanged

    在那裏,輸入方法public void Initialize(IPluginHost pluginHost),而是簡單地將PluginResolver.Init(path)沒有工作。

    主機程序使用WPF和螺紋,我不得不使用主機程序的調度輔助函數來得到它的工作:DispatcherHelper.Invoke(() => Resolver.Init(path));

如前所述,我目前不能確定哪種方法來使用,但我很高興我得到它的工作。感謝Corey!

+0

Duplicate:http://stackoverflow.com/a/2991971/1385688 –

+1

@DanielHäfele不是重複的。鏈接的應用程序處理應用程序,但這是特定於不能具有app.config的類庫的。這使得接受的答案不可能用於我的情況。 :(我曾嘗試使用AssemblyResolve事件,但最終因無法找到命名空間而無法編譯 – Bio2hazard

+0

@ Bio2hazard其實Daniel答案中的答案是正確的,並非接受的答案,但答案是建議添加'AssemblyResolve'處理程序,看到我的回答 – Corey

回答

1

您可以使用PATH環境變量將其他文件夾添加到搜索路徑。這適用於本機DLL,但我沒有嘗試將它用於.NET程序集。

另一種方法是在當前應用程序域上的AssemblyResolve事件中添加一個掛鉤,並使用自定義解析器從您找到它的任何位置加載相應的程序集。這可以在組件級完成 - 我使用它在NAudio.Lame中從資源加載程序集。

這些方針的東西:

public static class PluginResolver 
{ 
    private static bool hooked = false; 
    public static string PluginBasePath { get; private set; } 

    public static void Init(string BasePath) 
    { 
     PluginBasePath = BasePath; 
     if (!hooked) 
     { 
      AppDomain.CurrentDomain.AssemblyResolve += ResolvePluginAssembly; 
      hooked = true; 
     } 
    } 

    static Assembly ResolvePluginAssembly(object sender, ResolveEventArgs args) 
    { 
     var asmName = new AssemblyName(args.Name).Name + ".dll"; 
     var assemblyFiles = Directory.EnumerateFiles(PluginBasePath, "*.dll", SearchOption.AllDirectories); 

     var asmFile = assemblyFiles.FirstOrDefault(fn => string.Compare(Path.GetFileName(fn), asmName, true) == 0); 

     if (string.IsNullOrEmpty(asmFile)) 
      return null; 

     return Assembly.LoadFile(asmFile); 
    } 
} 

(Usings爲上述:System.IOSystem.ReflectionSystem.Linq

呼叫Init與基本路徑到您的插件文件夾中。當您嘗試引用尚未加載的程序集時,它將搜索與該程序集的基本名稱匹配的第一個文件,並附加dll。例如,NAudio程序集將匹配名爲NAudio.dll的第一個文件。它會加載並返回程序集。

上述代碼中沒有對版本等進行檢查,也沒有給出當前插件文件夾的優先權。

+0

你好,非常感謝你的回覆 我試過了PATH方法,但是沒有成功通過日誌記錄,我確認了路徑env var已經正確更新了,但是沒有好像它試圖從那裏加載NAudio 然後,我試着AssemblyResolve選項,我得到它的工作 丹尼爾的鏈接它把它放在Main() - 我試圖把它放到多個位置,但遇到了失敗(主機程序無法啓動 - 沒有日誌或任何東西) 感謝你的回答,我想通了,我可以把它放在一個靜態幫助函數。我確實需要調度Init()調用。 將更新我的問題。 – Bio2hazard

+0

很高興知道'PATH'選項不適用於.NET程序集加載。 – Corey

相關問題