ASP.NET Core MVC模块化设计如何实现深入解析?

摘要:ASP.NET Core MVC的“模块化”设计使我们可以构成应用的基本单元Controller定义在任意的模块(程序集)中,并在运行时动态加载和卸载。这种为“飞行中的飞机加油”的方案是如何实现的呢?该系列的两篇文章将关注于这个主题,本篇着
ASP.NET Core MVC的“模块化”设计使我们可以构成应用的基本单元Controller定义在任意的模块(程序集)中,并在运行时动态加载和卸载。这种为“飞行中的飞机加油”的方案是如何实现的呢?该系列的两篇文章将关注于这个主题,本篇着重介绍“模块化”的总体设计,下篇我们将演示将介绍“分散定义Controller”的N种实现方案。 一、ApplicationPart & AssemblyPart 二、ApplicationPartFactory & DefaultApplicationPartFactory 三、IApplicationFeatureProvider & IApplicationFeatureProvider<TFeature> 四、ControllerFeatureProvider 五、ApplicationPartManager 六、设计总览 七、有效Controller类型的提取 一、ApplicationPart & AssemblyPart MVC构建了一个抽象的模型来描述应用的组成。原则上来说,我们可以根据不同维度来描述当前的MVC应用由哪些部分构成,任何维度针下针对应用组成部分的描述都体现为一个ApplicationPart对象。因为没有限制对应用进行分解的维度,所以“应用组成部分”也是一个抽象的概念,它具有怎样的描述也是不确定的。也正是因为如此,对应的ApplicationPart类型也是一个抽象类型,我们只要任何一个ApplicationPart对象具有一个通过Name属性表示的名称就可以。 public abstract class ApplicationPart { public abstract string Name { get; } } 对于任何一个.NET Core应用来说,程序集永远是基本的部署单元,所以一个应用从部署的角度来看就是一组程序集。如果采用这种应用分解方式,我们可以将一个程序集视为应用一个组成部分,并可以通过如下这个AssemblyPart类型来表示。 public class AssemblyPart : ApplicationPart, IApplicationPartTypeProvider { public Assembly Assembly { get; } public IEnumerable<TypeInfo> Types => Assembly.DefinedTypes; public override string Name => Assembly.GetName().Name; public AssemblyPart(Assembly assembly) => Assembly = assembly; } 如上面的代码片段所示,一个AssemblyPart对象是对一个描述程序集的Assembly对象的封装,其Name属性直接返回程序集的名称。AssemblyPart类型还是实现了IApplicationPartTypeProvider接口,如下面的代码片段所示,该接口通过提供的Types属性提供当前定义在当前ApplicationPart范围内容的所有类型。AssemblyPart类型的Types属性会返回指定程序集中定义的所有类型。 public interface IApplicationPartTypeProvider { IEnumerable<TypeInfo> Types { get; } } 二、ApplicationPartFactory & DefaultApplicationPartFactory如下所示的抽象类ApplicationPartFactory表示创建ApplicationPart对象的工厂。如代码片段所示,该接口定义了唯一的GetApplicationParts方法从指定的程序集中解析出表示应用组成部分的一组ApplicationPart对象。 public abstract class ApplicationPartFactory { public abstract IEnumerable<ApplicationPart> GetApplicationParts(Assembly assembly); } 如下所示的DefaultApplicationPartFactory是ApplicationPartFactory最常用的派生类。
阅读全文