c#类库项目-从同一文件夹加载DLL?

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放在程序根目录中

我正在为现有的C#.NET程序开发一个插件。它的结构方式是,将自定义.dll文件放在程序根/Plugins/your plugin name/your plugin name.dll中

这一切都很好,但现在我正试图在我的项目中使用NAudio

我已经通过Nuget下载了NAudio,这部分工作正常,但问题是它在程序根目录中查找NAudio.dll,而不是在插件的文件夹中

这使得分发我的插件变得很困难,因为除了将插件放入“Plugins”文件夹外,还需要用户将NAudio.dll放在程序根目录中

资料来源: 设置视图.xaml:

<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();
    }
我找到了两种方法来实现这一点(我不确定这两种方法的优缺点是什么——如果有人知道我希望提供更多信息)

  • 使用NuGet软件包Costura.Fody

    安装NuGet包后,我只需将所有其他引用“Copy Local”设置为“False”,然后将NAudio的“Copy Local”设置为“True

    现在,当我构建时,NAudio.dll被压缩并添加到我自己的dll中

  • 使用下面概述的组装分解器

    但是,它并没有立即起作用,因此这里有一些额外的信息可以帮助任何面临相同问题的人:

    我把科里的密码放进了助手文件夹

    我的入口点是Plugin.cs,类是
    公共类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程序集加载。