2010-09-06 45 views
3

定义插件命令(包括链接插件)[我已经阅读MEF先前的文章VS MAF VS DI等,他们不帮我具体的问题]净插件框架的选择,使

我要找编写一个可扩展的.Net应用程序(可能是控制台或Windoes服务)。这是一个通宵/时间表应用程序,用于从数据库中提取数据,对数据进行处理,然后将其输出(或传递给另一个系统)。

我不确定什么是为插件定义此过程的最佳方法。的组件包括:

  • 任务 - 实际任务的定义,包含插件定义,和基于事件的标志上时运行(EOD,EOW,EOM)
  • - 的源数据(一个任务将有一个到多个来源),这可能是一个SQL查询/存储过程,Web服务或者一个文件。我看到这输出一个数据表。
  • 后期处理 - 需要在源输出上完成的处理(一个任务将具有非到多个后处理步骤),这可能是一个聚合器或某种特定的处理。这会收到一个数据集(包含上一步中的数据表)。由于依赖关系,这些必须按特定顺序运行。
  • 目标 - 最终的结果(也一对多),这可能是一个SQL语句/存储过程,一个专有的数据负载,电子邮件,输出文件或Web服务

为了简化它,我宁愿插件可以从配置文件读取,这意味着我不需要知道什么连接字符串(和其他细节)传递给插件。

我看过MEF,MAF,DI或者只是定义了我自己的框架。在这个阶段,我倾向于开发自己的产品,只是想知道我是否错过了什么?

我实际上想使用MEF,但是因为我需要定义我的任务(即任务链接指向哪个源链接到哪个PostProcess链接到哪个目标),并且也无法访问配置。我看到MEF Primatives和Type Catalogs让我成为其中的一部分,但似乎并没有帮助我链接插件。 MEF是一个有效的选择吗?

回答

3

MEF绝对是一个有效的选择。不过,我不认为MEF的设计是一个完全成熟的插件系统,它是一个很好的起点! MEF处理所有肮脏的装配加载和处理,但是任何特定的先决条件都需要手动检查。为此我建议使用元数据。元数据允许您使用可以读取的出口信息在导入前(MEF Metadata

[Export(typeof(ITask))] 
[ExportMetadata("Requires", "source1")] 
public class Task1: ITask 
{ 
    ... 
} 

通过与MEF是简单的路过的配置相关联。宿主应用程序可以导出它自己,所有插件都可以导入它并访问其接口。见我下面的例子:

接口:

public interface IMainApp 
{ 
    ConfigClass Config { get; set; } 
} 

主机应用程序:

[Export(typeof(IMainApp))] 
public class Host : IMainApp 
{ 
    public Host() 
    { /* Compose parts here..? */ } 

    public ConfigClass Config { get; set; } 

    [Import(typeof(IModule))] 
    public List<IModule> LoadedModules { get; set; } 
} 

插件组装:

[Export(typeof(IModule))] 
public class Module : IModule 
{   
    public Module() { } 

    [Import(typeof(IMainApp))] 
    public IMainApp Host { get; set; } 

    public void DoSomething() 
    { 
     Host.Config... // use config here 
    } 
} 
+0

感谢您的答复。 MEF元数据看起来非常有趣,我可以看到它的用途。不过,我认为这不会解决我的问题。 – 2010-09-07 13:00:12

+0

我希望能够使用不同的插件组合来定义任务,而无需编写任何代码。即Task1将Source1&Source2插入PreProcess1到Target1中,Task2将Source2插入PreProcess2插入Target1&Target2,Task3将Source3插入PreProcess2 Target2。但是任务定义“元数据”希望是某种配置,而不需要编译代码。我认为我需要在没有框架的情况下做到这一点,我仍然可以通过合同来做到这一点,至少可以使其具有可扩展性和可重用性。 – 2010-09-07 13:01:08

1

这听起来像你想做的事就是我们所说的明确的连线。 MEF默认情况下不支持这种方式,所以你必须跳过一些环节才能做到这一点。我相信MEF Contrib上有一个配置驱动的编程模型,它可以帮助你。

+0

我以前看过,最接近我发现的要求是 - [MEF的可配置类型目录](http://randomactsofcoding.blogspot.com/2010/01/configurable-type-catalog-for-mef.html) 。我想知道是否可以在配置文件中为每个任务定义定义一个新的自定义部分,然后只添加我感兴趣的类型/部分。我想我也可以在运行时使用Reflection来填充元数据,以强制执行我可能具有的任何链接规则(以确保按照上述评论中的示例遵循正确的顺序)。 – 2010-09-07 13:48:07

1

您可能想看看Mono.Addins。你可以为每个部分定义一个扩展点(所以插件可以定义新类型的源或目标),然后你可以创建一个扩展点来定义任务。在后面的扩展点中,您将定义每个任务以及它们与源和目标的关系。

例如,源可以在插件定义是这样的:

[Extension (Id="MySource")] 
class MySource: ISource 
{ 
    ... 
} 

以及用于定义任务的扩展点可能是这样的:

<Extension path="/MyApp/Tasks"> 
    <Task id="someTask"> 
     <Source sourceId="MySource" /> 
     <Target targetId="MyTarget" /> 
    </Task> 
    ... 
</Extension>