plugins - 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 插件?
解决方案
请试试这个:
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