代码之家  ›  专栏  ›  技术社区  ›  Ivan-Mark Debono

使用MEF加载插件时如何使用Hangfire?

  •  2
  • Ivan-Mark Debono  · 技术社区  · 7 年前

    我在WebApi项目中使用MEF加载位于bin文件夹以外的文件夹中的插件。我执行以下操作:

    var directoryCatalog = new DirectoryCatalog(Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "plugins"));
    
    var container = new CompositionContainer(directoryCatalog);
    container.ComposeParts();
    
    IList<IPlugin> plugins = container.GetExportedValues<IPlugin>().ToList();
    

    然后,我通过以下操作设置插件:

    plugins[0].Startup(logService, unitOfWork);
    

    注意:我没有使用 [ImportingConstructor] 传递上述依赖项,因为我使用的是控制器中已经实例化的现有实例。

    然后,我将工作安排如下:

    BackgroundJob.Schedule(() => plugins[0].Start(), new TimeSpan(0, 0, 1));
    

    但是,当Hangfire尝试启动作业时,我遇到以下异常:

    无法加载文件或程序集的应用程序。插件。FirstPlugin,Version=1.0.0.0,Culture=neutral,PublicKeyToken=null'或其依赖项之一。系统找不到指定的文件。

    在这种情况下,是否可能同时使用MEF和Hangfire?如果是,正确的程序是什么?

    注: 如果插件DLL与主应用程序位于同一个bin文件夹中,那么Hangfire工作正常。但这违背了拥有一个单独插件文件夹的目的。

    2 回复  |  直到 7 年前
        1
  •  4
  •   Evk    7 年前

    您需要通过订阅来指导hangfire(或者更确切地说是.NET本身)查找此程序集的位置 AppDomain.AssemblyResolve 事件(启动hangfire server之前的某处):

    var pluginPath = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "plugins");
    AppDomain.CurrentDomain.AssemblyResolve += (sender, args) => {
        var asmName = new AssemblyName(args.Name);
        var plugin = Path.Combine(pluginPath, asmName.Name + ".dll");
        if (File.Exists(plugin))
            return Assembly.LoadFrom(plugin);
        return null;
    };
    

    由于您的插件实际上已经加载到当前的应用程序域中(由MEF),因此以下内容也应该可以工作(我认为可能比上面更好):

    AppDomain.CurrentDomain.AssemblyResolve += (sender, args) => {
        var asmName = new AssemblyName(args.Name);
        var existing = AppDomain.CurrentDomain.GetAssemblies().FirstOrDefault(c => c.FullName == asmName.FullName);
        if (existing != null) {
            return existing;
        }
        return null;
    };
    

    这是必要的,因为为了从数据库中的状态反序列化插件实例,hangfire使用 Type.GetType 提供程序集限定名称,并且由于某些(我认为)与此问题无关的复杂性- 类型获取类型 将找不到您的插件程序集,即使它已经由MEF加载到当前的应用程序域中,所以您必须稍微帮助它。

        2
  •  1
  •   Emiel Koning    7 年前

    Hangfire Extensions page,有一个NuGet包的概念 机关枪。MEF公司 .

    它导致 Hangfire.MEF - Hangfire background job activator based on MEF IoC Container . 我想这可能会帮助你解决你的问题。