首页 > 解决方案 > MEF - 加载依赖项

问题描述

我正在使用 .net 核心开发一个 MEF 插件。插件使用Entity Framework,只有插件项目引用Entity Framework。我创建了 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 插件?

标签: pluginsmefsystem.reflection

解决方案


请试试这个:

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


推荐阅读