使用MEF,Web应用程序中的可扩展点是什么?

时间:2014-05-18 11:21:29

标签: asp.net-mvc design-patterns mef

因此,我决定在我的新ASP.NET MVC Web项目中使用Microsoft可扩展性框架(MEF)。该项目是一个非常典型的员工管理系统,有3个传统层: - 一个表示层(带有视图和控制器),一个业务层(带有业务对象)和一个数据访问层。经过一些研究,我读了很多,MEF应该帮助我们实现插件架构。而这就是我在哪里,我似乎陷入困境。我无法与这个可插拔的部分联系起来。我非常确定,因为MEF是核心.NET框架的一部分,所以它不仅限于任何特定类型的应用程序,并且应该是有用的。我只需要以全新的视角看待我的应用程序结构,并且我需要一些有用的见解。

由于我还在尝试开始使用MEF,我的主要问题是;什么是我的应用程序中的主要可扩展(可插入)点?应该使用MEF的组合方法构建哪些对象,以及使用MEF而不是传统方式这样做的优势是什么?

1 个答案:

答案 0 :(得分:1)

在您在问题中描述的情况下,MEF不会帮助您解决可扩展性问题,因为它似乎没有任何问题。对于这种特殊情况,MEF可以带来什么是依赖注入。如果您以表示层依赖于业务抽象的方式开发应用程序,并且业务层依赖于数据访问抽象而不是具体实现,那么您将获得易于测试,维护和更改的高度分离的应用程序,而不会影响不必要的组件这是一种方法:

假设您拥有对员工执行CRUD操作的数据访问类:

[Export(typeof(IEmployeeRepository))]
public class EmployeeRepository : IEmployeeRepository
{
    //Some logic here
}

正如您所见,EmployeeRepository类实现了IEmployeeRepository接口,它增加了开发解耦应用程序所需的抽象级别。现在我们可以说,在业务层中,您有一个需要从EmployeeRepository类调用某个方法的类。为了能够调用EmployeeRepository的方法,您需要一个实例。如果不使用MEF(或任何其他IoC框架,这将是一种方法:

public class EmployeeManager
{
    private EmployeeRepository _employeeRepository;

    public EmployeeManager
    {
        _employeeRepository = new EmployeeRepository();
    } 
}

通过使用上面的代码示例,创建了EmployeeManagerEmployeeRepository类之间的硬依赖关系。在编写单元测试时,这种硬依赖很难被隔离,并导致EmployeeRepository类的任何更改直接影响EmployeeManager类。通过稍微重构代码示例并将MEF放入游戏中,您将得到:

[Export(typeof(IEmployeeManager))]
public class EmployeeManager : IEmployeeManager
{
    private IEmployeeRepository _employeeRepository;

    [ImportingConstructor]
    public EmployeeManager(IEmployeeRepository employeeRepository)
    {
        _employeeRepository = employeeRepository;
    } 
}

正如您所看到的,EmployeeManager类现在不依赖于EmployeeRepository类,但它依赖于IEmployeeRepository接口,换句话说它取决于抽象。并且它本身不会创建EmployeeRepository类的实例。这项工作留给了MEF。到目前为止,应该清楚导出和ImportingConstructor属性是MEF的一部分,并由它用于发现部件并在运行时解决依赖关系。使用最后一个代码示例,这些类是分离的,易于测试和维护,您可以在EmployeeRepository类中更改内部逻辑,而无需让EmployeeManager类知道它。当然,他们之间的合同IEmployeeRepository必须保持。

如上所述,也可用于将表示层与业务层分离。上面说的,可以通过使用任何其他IoC框架来实现,如Ninject,Autofac,StructureMap等。这些IoC框架和MEF之间的区别在于,如果你使用它们,你需要在应用程序启动时配置哪个实例得到在遇到某个接口时创建:

//something like this, in the case of Ninject
this.Bind<IEmployeeRepository>().To<EmployeeRepository>();

另一方面,MEF具有在运行时发现部件的能力。在应用程序启动时,您只需要告知它在哪里查找部件:目录,装配,类型等.MEF的自动连线功能(在运行时发现部件的能力),使其不仅仅是常规的IoC框架。这种能力使MEF非常适合开发可插拔和可扩展的应用程序,因为您可以在应用程序运行时添加插件。 MEF可以加载它们并让应用程序使用它们。