.net core依赖注入与MVC

1,114 阅读3分钟

.net core中服务注册的几种方式

IServiceCollection的Add方法

首先要知道在Startup配置类中有两个方法比较重要的方法,ConfigureConfigureServices方法,前者经常用来添加中间件,后者则是我们注册服务的位置。 IServicesCollectionAdd方法接受一个ServiceDescriptor对象为参数,以下是官方文档给出的构造函数:

不难看出大致有这样几个参数:IService接口类型、InstanceObject表示具体的实现类,最后一个参数表示服务的生命周期,给一段示例代码:

// This method gets called by the runtime. Use this method to add services to the container.
public void ConfigureServices(IServiceCollection services)
{
    services.Add(new ServiceDescriptor(typeof(IMyService), typeof(MyService), ServiceLifetime.Scoped));
    services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_1);
}

不难理解,IServiceCollection实际上是一个ServiceDescriptor类型的集合,用接口类型、接口实现类和生命周期来描述容器中的服务。

服务的生命周期

  • Singleton:容器会创建并共享服务的单例,且一直会存在于应用程序的整个生命周期内。
  • Transient:每次服务被请求时,总会创建新实例。
  • Scoped:在每一次请求时会创建服务的新实例,并在这个请求内一直共享这个实例。

生命周期扩展方法

 //Singleton
  services.AddSingleton(typeof(IMyService), typeof(MyService));
  services.AddSingleton<IMyService,MyService>();
  services.AddScoped<IMyService>(temp => new MyService());

  //Scoped
  services.AddScoped(typeof(IMyService), typeof(MyService));
  services.AddScoped<IMyService, MyService>();
  services.AddScoped<IMyService>(temp => new MyService());

给一张官网文档的截图,推荐使用上述示例代码中最后一种方式(因为支持的特性最多)

依赖项的几种注入方式

构造器注入

[Route("api/[controller]")]
[ApiController]
public class ValuesController : ControllerBase
{
    private readonly IMyService myService;

    public ValuesController(IMyService myService)
    {
        this.myService = myService;
    }
    // GET api/values
    [HttpGet]
    public ActionResult<IEnumerable<string>> Get()
    {
        return new string[] { "value1", "value2" };
    }
}

FromServices方法注入

public IActionResult About([FromServices] IDateTime dateTime)
{
    return Content( $"Current server time: {dateTime.Now}");
}

从json配置文件读取配置

------------华丽的分割线--------
不巧没用过,不会
官方文档:服务的依赖注入注册
将依赖项注入到Controller

MVC

要在ASP.NET Core中使用MVC,首先需要在Startup类中添加MVC中间件: Configure方法:

public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
    app.UseMvc();
}

ConfigureServices方法:

public void ConfigureServices(IServiceCollection services)
{
    services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_1);
}

路由

在.net core MVC中路由负责解析URL,并将拆解出来的信息处理后把请求交给特定Controller中的特定Action,Action是在controller中的方法,将请求处理完毕后返回特定的视图View(可能是Razor生成的cshtml也可能是html)或者特定格式的数据(JSON)。

比较麻烦的方式创建路由

先从不好学的学起方便后续理解。

1.添加路由相关的服务

public void ConfigureServices(IServicesCollection services){
    services.AddRouting();
}

2.配置路由中间件

public void Configure(IApplicationBuilder app,IHostingEnironment evn)
{
    //创建路由处理器RouteHandler,输出路由信息
    var routeHandler = new RouteHandler(context =>
    {
        var values = context.GetRouteData().Values;
        return context.Response.WriteAsync($"路由信息{string.Join(",", values)}");
    });
    //创建RouteBuilder
    var routeBuilder = new RouteBuilder(app, routeHandler);
    //MapRoute方法
    routeBuilder.MapRoute("api/hello", context =>
        {
            return context.Response.WriteAsync(JsonConvert.SerializeObject(new
            {
                name="hello路由",
                message="返回一个JSON对象"
            }));
        });
    routeBuilder.MapRoute("Route1", "api/{operation}/{id:int}");
    routeBuilder.MapGet("hello/{prama1}", context =>
    {
        var prama1 = context.GetRouteValue("prama1");
        return context.Response.WriteAsync($"hello后参数:{prama1}");
    });
    routeBuilder.MapRoute("default", "api/{Controller}/{Action}");
    IRouter routes = routeBuilder.Build();
    //调用IApplicationBuilder的UseRouter扩展方法来添加路由中间件
    app.UseRouter(routes);
}

RouteHandler只有一个构造器,没有重载,接受RequestDelegate类型的参数。 RequestDelegate接收一个HttpContext类型的参数返回值为Task类型。 以下是几种匹配路由的结果:

  • 匹配到第一个路由:

  • 匹配到第二个路由

  • 匹配到第三个路由

  • 默认路由

除了IApplicationBuilder的UseRouter方法外,在添加MVC中间件时使用的UseMvc方法也可以配置路由信息,以下是UseMvc的方法签名:

可以看到其中一个扩展方法接受Action(这个Action是一个委托,接受一个IRouteBuilder类型的参数),这就有操作空间了,所以路由还可以这么写: 用UseMvc扩展方法配置路由:

//UseMvc方法:
app.UseMvc(routes =>
{
routes.MapRoute(
    name:"myRoute",
    template:"{controller}/{action}",
    defaults: new { Controller = "My", Action = "Hello"}
    );
});
//Controller
public class MyController: Controller
{
    public IActionResult Hello()
    {
        return Ok("这里是HelloAction");
    }
}

请求以及响应结果:

正经人写的路由

因为上面的写法有些是2.1版本的(其实.net framework里面路由就这么写),下面继续学习3.1