c#类库项目-从同一文件夹加载DLL?
我正在为现有的C#.NET程序开发一个插件。它的结构方式是,将自定义.dll文件放在程序根/Plugins/your plugin name/your plugin name.dll中 这一切都很好,但现在我正试图在我的项目中使用NAudio 我已经通过Nuget下载了NAudio,这部分工作正常,但问题是它在程序根目录中查找NAudio.dll,而不是在插件的文件夹中 这使得分发我的插件变得很困难,因为除了将插件放入“Plugins”文件夹外,还需要用户将NAudio.dll放在程序根目录中 资料来源: 设置视图.xaml:c#类库项目-从同一文件夹加载DLL?,c#,.net,dll,using,naudio,C#,.net,Dll,Using,Naudio,我正在为现有的C#.NET程序开发一个插件。它的结构方式是,将自定义.dll文件放在程序根/Plugins/your plugin name/your plugin name.dll中 这一切都很好,但现在我正试图在我的项目中使用NAudio 我已经通过Nuget下载了NAudio,这部分工作正常,但问题是它在程序根目录中查找NAudio.dll,而不是在插件的文件夹中 这使得分发我的插件变得很困难,因为除了将插件放入“Plugins”文件夹外,还需要用户将NAudio.dll放在程序根目录中
<Button HorizontalAlignment="Center"
Margin="0 5"
Width="120"
Command="{Binding SoundTestCommand,
Source={StaticResource SettingsViewModel}}"
Content="Sound Test" />
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#在程序根/Plugins/my plugin name/NAudio.dll中查找NAudio,而不是在程序根/NAudio.dll中查找它
我使用的是VS Express 2013,目标框架是4.5,输出类型是类库
编辑:
<Button HorizontalAlignment="Center"
Margin="0 5"
Width="120"
Command="{Binding SoundTestCommand,
Source={StaticResource SettingsViewModel}}"
Content="Sound Test" />
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();
}
我找到了两种方法来实现这一点(我不确定这两种方法的优缺点是什么——如果有人知道我希望提供更多信息)
公共类Plugin:IPlugin,INotifyPropertyChanged
在这里,输入方法是public void Initialize(IPluginHost pluginHost)
,但是简单地将PluginResolver.Init(path)
放进去是不起作用的
宿主程序使用WPF并且是线程化的,我必须使用宿主程序的DispatcherHelper函数才能使其工作:DispatcherHelper.Invoke(()=>Resolver.Init(path))代码>
如前所述,我目前不确定使用哪种方法,但我很高兴我得到了它的工作。谢谢你,科里 您可以使用
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);
}
}
(上面的用法:System.IO
,System.Reflection
,System.Linq
)
使用插件文件夹的基本路径调用Init
。当您尝试引用尚未加载的程序集时,它将搜索与附加了dll
的程序集基名称匹配的第一个文件。例如,NAudio
程序集将匹配名为NAudio.dll
的第一个文件。然后,它将加载并返回部件
上述代码中没有对版本等进行检查,也没有优先选择当前插件的文件夹。Duplicate:@DanielHäfele不是重复的。链接的一个处理应用程序,而这是特定于类库的,类库不能有app.config。这使得在我的案例中无法使用公认的答案:(我试图使用AssemblyResolve事件,但由于找不到命名空间,我最终无法编译。@实际上Daniel链接到的答案是完全正确的。不是接受的答案,而是建议添加
AssemblyResolve
处理程序的答案。请参阅我的答案。您好,非常感谢您的回答。我尝试了PATH方法,但没有成功。通过日志记录,我确认PATH env var已正确更新,但它似乎没有试图从那里加载NAudio。然后,我尝试了AssemblyResolve选项,并使其正常工作。Daniel的链接已将其放入Main()中-我尝试将其放入多个位置,但遇到了失败。(主机程序无法启动-没有日志或任何内容)多亏了您的回答,我发现我可以将其放入静态助手函数中。我确实必须调度Init()调用。将更新我的问题。很高兴知道PATH
选项不适用于.NET程序集加载。