首页 > 编程语言 >深入解析ASP.NET Core MVC的模块化设计[下篇]

深入解析ASP.NET Core MVC的模块化设计[下篇]

时间:2024-03-06 09:00:55浏览次数:30  
标签:Core ASP Bar 程序 ApplicationPartManager Controller MVC new Foo

ASP.NET Core MVC的“模块化”设计使我们可以构成应用的基本单元Controller定义在任意的模块(程序集)中,并在运行时动态加载和卸载。《设计篇》介绍了这种为“飞行中的飞机加油”的方案的实现原理?本篇我们将演示将介绍“分散定义Controller”的N种实现方案。源代码从这里下载。

一、标注ApplicationPartAttribute特性
二、标注RelatedAssemblyAttribute特性
三、注册ApplicationPartManager
四、添加ApplicationPart到现有ApplicationPartManager

一、标注ApplicationPartAttribute特性

接下来我们就通过几个简单的实例来演示如何将Controller类型定义在非入口应用所在的项目中。我们创建如图1所示的解决方案,其中App是一个MVC应用类型的项目,而Foo则是一个普通的类库项目,App具有针对Foo的项目引用。我们希望将部分Controller类型定义在Foo这个类库项目中。

image_thumb[12]

图1 将部分Controller类型定义在Foo项目中

我们在App项目中定义了如下这个HomeController。如代码片段所示,我们在构造函数中注入了ApplicationPartManager对象,并利用它得到当前应用范围内所有有效Controller类型。在执行应用根路径的Action方法Index中,我们将得到的有效Controller类型名称呈现出来。如下所示的FooController类型是我们在Foo项目中定义的Controller类型。

public class HomeController : Controller
{
    private readonly IEnumerable<Type> _controllerTypes;
    public HomeController(ApplicationPartManager manager)
    {
        var feature = new ControllerFeature();
        manager.PopulateFeature(feature);
        _controllerTypes = feature.Controllers;
    }

    [HttpGet("/")]
    public string Index()
    {
        var lines = _controllerTypes.Select(it => it.Name);
        return string.Join(Environment.NewLine, lines.ToArray());
    }
}

public class FooController
{
    public void Index() => throw new NotImplementedException();
}

在启动这个演示程序后,如果利用浏览器通过根路径访问定义在HomeController类型中的Action方法Index,我们会得到如图2所示的输出结果。从输出结果可以看出,定义在非MVC应用项目Foo中的Controller类型在默认情况下是不会被解析的。

image_thumb[14]

图2 默认只解析MVC应用所在项目定义的Controller

如果希望MVC应用在进行Controller类型解析的时候将项目Foo编译后的程序集(默认为Foo.dll)包括进来,我们可以在应用所在项目中标注ApplicationPartAttribute特性将程序集Foo作为应用的组成部分。所以我们在Program.cs中针对ApplicationPartAttribute特性进行了如下的标记。

[assembly:ApplicationPart("Foo")]

修改后的程序集启动之后,再次利用浏览器按照按照相同的路径对它发起请求,我们将得到如图3所示的输出结果。由于程序集Foo成为了当前应用的有效组成部分,定义在它里面的BarController自然也成为了当前应用有效的Controller类型。

image_thumb[16]

图3 解析ApplicationPartAttribute特性指向程序集中的Controller类型

二、标注RelatedAssemblyAttribute特性

除了在入口程序集上标注ApplicationPartAttribute特性将某个程序集作为当前应用的有效组成部分之外,我们也可以通过标注RelatedAssemblyAttribute达到相同的目的。根据前面的介绍,我们知道RelatedAssemblyAttribute特性只能标注到入口程序集或者ApplicationPartAttribute特性指向的程序集中,所以我们可以将RelatedAssemblyAttribute特性标注到Foo项目中将另一个程序集包含进行。为此我们在解决方案中添加了另一个类库项目Bar(如图4所示),并为App添加针对Bar的项目引用,然后在Bar项目中定义一个类似于FooController的BarController类型。

image_thumb[19]

图4 将部分Controller类型定义在Foo和Bar项目中

为了将项目Bar编译后生成的程序集(默认为Bar.dll)作为当前应用的组成部分,我们可以选择在App或者Foo项目中标注一个指向它的RelatedAssemblyAttribute特性。对于我们演示的实例来说,我们选择在FooController.cs中以如下形式标注一个指向程序集Bar的RelatedAssemblyAttribute特性。

[assembly: RelatedAssembly("Bar")]

修改后的程序集启动之后,再次利用浏览器按照按照相同的路径对它发起请求,我们将得到如图5所示的输出结果。由于程序集Bar成为了当前应用的有效组成部分,定义在它里面的BazController自然也成为了当前应用有效的Controller类型。

image_thumb[21]

图5 解析RelatedAssemblyAttribute特性指向程序集中的Controller类型

三、注册ApplicationPartManager

由于针对有效Controller类型的解析是利用注册的ApplicationPartManager对象实现的,所以我们完全可以通过注册一个ApplicationPartManager对象的方式达到相同的目的。接下来我们将上一个演示实例中标注的ApplicationPartAttribute和RelatedAssemblyAttribute特性删除,并将承载程序修改为如下的形式。

var manager = new ApplicationPartManager();
var entry = Assembly.GetEntryAssembly()!;
var foo = Assembly.Load(new AssemblyName("Foo"));
var bar = Assembly.Load(new AssemblyName("Bar"));

manager.ApplicationParts.Add(new AssemblyPart(entry));
manager.ApplicationParts.Add(new AssemblyPart(foo));
manager.ApplicationParts.Add(new AssemblyPart(bar));
manager.FeatureProviders.Add(new ControllerFeatureProvider());


var builder = WebApplication.CreateBuilder(args);
builder.Services
    .AddSingleton(manager)
    .AddControllers();
var app = builder.Build();
app.MapControllers();
app.Run();

如上面的代码片段所示,我们创建了一个ApplicationPartManager对象,并在其ApplicationParts属性中显式添加了指向入口程序集以及Foo和Bar程序集的AssemblyPart对象。为了能够让这个ApplicationPartManager对象具有解析Controller类型的能力,我们在其FeatureProviders中添加了一个ControllerFeatureProvider对象。在后续的应用承载程序中,我们将这个ApplicationPartManager对象作为服务注册到依赖注入框架中。修改后的程序集启动之后,再次利用浏览器按照按照相同的路径对它发起请求,我们依然会得到如图5所示的输出结果。

四、添加ApplicationPart到现有ApplicationPartManager

其实我们没有必要注册一个新的,按照如下的方式将Foo、Bar程序集转换成AssemblyPart并将其添加到现有的ApplicationPartManager之中也可以达到相同的目的。

var builder = WebApplication.CreateBuilder(args);
builder.Services
    .AddControllers()
    .AddApplicationPart(Assembly.Load(new AssemblyName("Foo")))
    .AddApplicationPart(Assembly.Load(new AssemblyName("Bar")));
var app = builder.Build();
app.MapControllers();
app.Run();

标签:Core,ASP,Bar,程序,ApplicationPartManager,Controller,MVC,new,Foo
From: https://www.cnblogs.com/artech/p/18052365

相关文章

  • .NET6 + EF Core + MySQL 创建实体和数据库、EFCore 数据迁移、属性导航
    一、创建asp.netcoreweb(MVC)项目二、导包Microsoft.EntityFrameworkCore.DesignMicrosoft.EntifyFrameworkCore.ToolsPomelo.EntityFrameworkCore.MySql三、创建实例这里创建了两个实例namespacedemo.Models{publicclassSupplier{[DatabaseGe......
  • InnoDB存储引擎对MVCC的实现
    一 多版本并发控制(Multi-VersionConcurrencyControl)1、读操作(SELECT):当一个事务执行读操作时,它会使用快照读取。快照读取是基于事务开始时数据库中的状态创建的,因此事务不会读取其他事务尚未提交的修改。具体工作情况如下:对于读取操作,事务会查找符合条件的数据行,并选择符......
  • 开源:Taurus.Idempotent 分布式幂等性锁框架,支持 .Net 和 .Net Core 双系列版本
    分布式幂等性锁介绍:分布式幂等性框架的作用是确保在分布式系统中的操作具有幂等性,即无论操作被重复执行多少次,最终的结果都是一致的。幂等性是指对同一操作的多次执行所产生的效果与仅执行一次的效果相同。以下是分布式幂等性框架的主要作用:避免重复操作:在分布式系统中,由于......
  • springMVC执行流程--
    springMVC执行流程1.springMVC执行流程Springmvc的执行流程是这个框架最核心的内容视图阶段(老旧JSP等)前后端分离阶段(接口开发,异步)2.视图阶段(jsp)重要的组件:前端控制器、处理器映射器、处理器适配器、视图解析器3.前后端分离阶段(接口开发,异步)4.问题总结......
  • .Net Core(七) 管道和中间件
    简介管道.NETCore中的管道是一个用于处理HTTP请求的组件。它是ASP.NETCore应用程序的核心部分,负责将传入的HTTP请求传递给适当的处理程序并生成响应。管道由一系列中间件组成,每个中间件都可以对请求或响应进行操作,然后将其传递给下一个中间件或终止请求处理。中间件......
  • 【HMS Core】集成推送服务,打包后应用名乱码
    ​【问题描述】使用flutter进行移动端开发,导入了agconnect-services.json之后,成功集成了华为推送,但是应用打包如果应用名为中文,debug包生成的应用名会是乱码。​​ 【问题分析】1、经推测可能是agc插件与开发者引入的另外的sdk相冲突导致的,但即使去掉其他的sdk也会导致该问......
  • asp.net core 中基于策略的授权-自定义授权
    前两篇文章扫盲篇,进阶篇中介绍了基本的asp.netcore中基于策略的授权的使用方法。使用策略授权时,只能指定策略,不能配置其他信息。[Authorize(Policy="AtLeast21")]//指定要验证的策略publicclassAlcoholPurchaseController:Controller{publicIA......
  • NetCore3.1 引入PostgerSql + DbFirst
    十年河东,十年河西,莫欺少年穷学无止境,精益求精1、新建控制台项目PostgreSQLApp,引入如下包<ProjectSdk="Microsoft.NET.Sdk"><PropertyGroup><OutputType>Exe</OutputType><TargetFramework>netcoreapp3.1</TargetFramework></Prope......
  • ASP.NET Core - 配置系统之配置读取
    一个应用要运行起来,往往需要读取很多的预设好的配置信息,根据约定好的信息或方式执行一定的行为。配置的本质就是软件运行的参数,在一个软件实现中需要的参数非常多,如果我们以HardCode(硬编码)的方式写在应用代码中,这样配置就会很乱,而且后续也不容易修改。乱而多,而且不容易修改,......
  • ASP.NET Core策略授权和ABP授权
    首先我们来创建一个WebAPI应用。然后引入Microsoft.AspNetCore.Authentication.JwtBearer包。策略Startup类的ConfigureServices方法中,添加一个策略的形式如下:services.AddAuthorization(options=>{options.AddPolicy("AtLeast21",policy=>......