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最常用的派生类。
