2 个使用具有不同提供程序的实体框架的 MEF 插件



我有一个WPF应用程序,我的用户可以使用MEF创建自己的插件。每个插件都实现了一个接口,允许主应用程序对某些数据源(例如数据库)执行 CRUD 操作。

我创建了 2 个插件:

  • 本地数据库 - 提供来自SQLite数据库的数据
  • 远程数据库 - 提供来自 MySQL 数据库的数据

两者都使用实体框架来完成其工作。这些插件中的每一个都需要有自己的DbConfiguration类实现。

现在,问题是 WPF 应用程序加载了这两个插件,但无法为每个插件分配自己的 DbConfiguration 类实现,因为似乎每个 AppDomain 只能有一个 DbConfiguration。 所以我总是只有一个插件在工作。

我正在考虑只有一个 DbConfiguration 类的实现,并为每个插件提供一个选项来添加其所需的配置,但问题是它在 WPF 应用程序和实体框架之间创建了某种耦合。我想将实体框架的东西只保留在插件中,而无需修改 WPF 应用程序。它不应该关心哪些插件使用什么来访问其数据源。

有没有办法让它以这种方式工作?我可以以某种方式为每个插件创建一个单独的 AppDomain 吗,那么也许每个插件都可以使用自己的 DbConfiguration 类?

我找到了一个有点笨拙的解决方案,但它似乎确实有效,所以我想我会发布它,以防万一,有人将来会在某个地方遇到同样的问题。

经过一些额外的研究,我了解到可以使用DbConfiguration.Loaded事件为 EF 注册一些其他依赖项解析程序。因此,在每个插件的构造函数中,我订阅了该事件并添加了一个新的依赖项解析器:用于LocalDatabase的SQLite和用于RemoteDatabase的MySql。我摆脱了每个插件的自定义DbConfiguration类。

这看起来很有希望,但实际上出现了一个新问题 - 在某些情况下,LocalDatabase插件调用 MySql 解析器,它实际上返回了所请求服务类型的 MySql 实现。显然,LocalDatabase插件无法使用它,因为它需要SQLite实现。反之亦然。

因此,每个解析程序实际上都需要检查谁调用了GetService方法 - 如果它是自定义解析程序所在的同一程序集中的某个方法,它将尝试解析。否则,假设来自不同插件的解析器应该处理该请求,并且它返回 null 以实际让它这样做。

问题是GetService方法不提供有关请求者的任何信息。这就是我想出黑客解决方案的地方,它使用StackTrace来检查任何被调用的方法是否属于当前解析器所在的同一Assembly

public class CustomMySqlDbDependencyResolver : IDbDependencyResolver
{
private readonly Assembly _executingAssembly = Assembly.GetExecutingAssembly();
private readonly MySqlDependencyResolver _mySqlResolver = new MySqlDependencyResolver();
public object GetService(Type type, object key)
{
var stackTrace = new StackTrace();
StackFrame[] stackFrames = stackTrace.GetFrames().Skip(1).ToArray();
bool shouldResolve = stackFrames.Any(f => f.GetMethod().DeclaringType.Assembly.Equals(_executingAssembly));
if (!shouldResolve)
{
return null;
}
var resolvedService = _mySqlResolver.GetService(type, key);
return resolvedService;
}
public IEnumerable<object> GetServices(Type type, object key)
{
var service = GetService(type, key);
if (service != null)
{
yield return service;
}
}
}

最新更新