2013-12-16 62 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

相关问题