MEF - 加载依赖项

时间:2021-06-17 15:01:11

标签: plugins mef system.reflection

我正在使用 .net 核心开发 MEF 插件。插件使用实体框架,只有插件项目引用实体框架。我创建了 CompositionContainer,但是当我访问插件时,我得到了这个异常:

<块引用>

无法加载文件或程序集“Microsoft.EntityFrameworkCore,

我有一个定义接口的项目:

namespace MyInterfaces
{
    public interface IShowMessage
    {
        void ShowMessage();
    }
}

主项目加载插件:

namespace MainApp
{
    public class DoWork
    {
        private CompositionContainer _container;
        [Import(typeof(IShowMessage))]
        public IShowMessage MyMessage;
        public DoWork()
        {
            var catalog = new AggregateCatalog();
            catalog.Catalogs.Add(new AssemblyCatalog(GetOtherAssembly()));
            _container = new CompositionContainer(catalog);
            _container.ComposeParts(this);
            MyMessage.ShowMessage();
        }
        private Assembly GetOtherAssembly()
        {
            var assembly = AssemblyLoadContext.Default.LoadFromAssemblyPath(Directory.GetCurrentDirectory() + @"\..\..\..\..\MyPlugin\bin\debug\netstandard2.1\MyPlugin.dll");
            return assembly;
        }
    }
}

以及一个实现接口的插件项目:

namespace MyPlugin
{
    [Export(typeof(IShowMessage))]
    public class ShowComplexMessage : IShowMessage
    {
        public void ShowMessage()
        {
            DbSet<String> str;
            Console.Write("Complex Message");
        }
    }
}

'DbSet str;'行在插件参考 EntityFramework 中。如果我注释掉这一行,它可以正常工作。

我注意到我的插件项目的 bin 文件夹没有 EntityFramework dll。如果我使用 dotnet publish,我可以生成 EntityFramework dll,但这并不能解决问题。 如果我显式加载“Microsoft.EntityFrameworkCore”。我在 ComposeParts 行收到一个异常,告诉我它无法加载实体框架使用的程序集。

我已尝试将所有 DLL 添加到目录中,但有些加载失败(可能是绑定重定向?)。我认为我正在为一些常见且可能已解决的问题走上错误的道路。 ***编辑 - 这就是 DirectoryCatalog 所做的,但没有帮助。 ***

我也尝试过使用反射创建插件的实例,但我遇到了类似的错误。

如何加载带有插件依赖项的 MEF 插件?

1 个答案:

答案 0 :(得分:0)

请试试这个:

public class ModuleAssemblyLoadContext : AssemblyLoadContext
{
    private readonly AssemblyDependencyResolver resolver;

    internal ModuleAssemblyLoadContext(string assemblyPath) : base(true)
    {
        resolver = new AssemblyDependencyResolver(assemblyPath);

        ResolvingUnmanagedDll += OnResolvingUnmanaged;

        Resolving += OnResolving;
    }

    private IntPtr OnResolvingUnmanaged(Assembly assembly, string unmanagedName)
    {
        string unmanagedPath = resolver.ResolveUnmanagedDllToPath(unmanagedName);

        return unmanagedPath != null ? LoadUnmanagedDllFromPath(unmanagedPath) : IntPtr.Zero;
    }

    private Assembly OnResolving(AssemblyLoadContext context, AssemblyName assemblyName)
    {
        string assemblyPath = resolver.ResolveAssemblyToPath(assemblyName);

        return assemblyPath != null ? LoadFromAssemblyPath(assemblyPath) : null;
    }
}

代码中的下一个:

    private Assembly GetOtherAssembly()
    {
        string path = Directory.GetCurrentDirectory() + @"\..\..\..\..\MyPlugin\bin\debug\netstandard2.1\MyPlugin.dll";

        ModuleAssemblyLoadContext context = new ModuleAssemblyLoadContext(path);

        return context.LoadFromAssemblyPath(path);
    }

当然,请确保您的插件所需的任何依赖项都存在于您的插件 dll 所在的文件夹中。

您可以在这里找到更完整的实现:

https://github.com/qube7/qcomposite/blob/master/Qube7.Composite/Hosting/AssemblyModule.cs