1.ASP.NET Core MVC依赖注入

1.依赖注入步骤

步骤一:使用接口或基类将依赖关系实现抽象化。

//IMyDependency接口定义了WriteMessage方法
public interface IMyDependency
{
    void WriteMessage(string message);
}

//MyDependency具体类实现了IMyDependency接口
public class MyDependency : IMyDependency
{
    public void WriteMessage(string message)
    {
        Console.WriteLine($"MyDependency.WriteMessage Message: {message}");
    }
}

步骤二:使用 builder.Services 提供的服务注册方法在内置的DI服务容器 IServiceProvider 中注册服务。

using DependencyInjectionSample.Interfaces;
using DependencyInjectionSample.Services;

//创建WebApplicationBuilder类的实例
//builder已将 配置、日志记录和许多其它服务 添加到 DI 容器中。
var builder = WebApplication.CreateBuilder(args);

//调用Services返回IServiceCollection接口实例
//使用AddScoped服务注册方法(服务生存期是范围内的)注册IMyDependency服务和MyDependency具体类。

builder.Services.AddScoped<IMyDependency, MyDependency>();

var app = builder.Build();

步骤三:将服务注入到使用它的类的构造函数中。

public class Index2Model : PageModel
{
    private readonly IMyDependency _myDependency;

    public Index2Model(IMyDependency myDependency)
    {
        _myDependency = myDependency;            
    }

    public void OnGet()
    {
        _myDependency.WriteMessage("Index2Model.OnGet");
    }
}

2.使用扩展方法注册服务组

2.1内置服务组

约定使用单个 Add{GROUP_NAME} 扩展方法来注册一组相关服务。比如:AddRazorPagesAddControllersAddControllersWithViewsAddDbContext 和 AddDefaultIdentity等等。

2.1自定义服务组

var builder = WebApplication.CreateBuilder(args);

builder.Services.AddRazorPages();

builder.Services.Configure<PositionOptions>(
    builder.Configuration.GetSection(PositionOptions.Position));
builder.Services.Configure<ColorOptions>(
    builder.Configuration.GetSection(ColorOptions.Color));

var app = builder.Build();

可以将相关的注册组移动到扩展方法以注册服务。

建议应用遵循在 Microsoft.Extensions.DependencyInjection 命名空间中创建扩展方法的Add{GROUP_NAME}命名约定。

namespace Microsoft.Extensions.DependencyInjection
{
    public static class MyConfigServiceCollectionExtensions
    {
        public static IServiceCollection AddConfig(
             this IServiceCollection services, IConfiguration config)
        {
            services.Configure<PositionOptions>(
                config.GetSection(PositionOptions.Position));
            services.Configure<ColorOptions>(
                config.GetSection(ColorOptions.Color));

            return services;
        }
    }
}
var builder = WebApplication.CreateBuilder(args);

builder.Services.AddConfig(builder.Configuration);

builder.Services.AddRazorPages();

var app = builder.Build();

3.服务生存期

生存期长度:单例生存期>范围内生存期>暂时生存期,所以从暂时或其它范围内生存期服务可以解析范围内生存期服务,从暂时或范围内生存期服务可以解析单例生存期服务。从具有较长生存期的其它服务解析服务将会引发异常。

生存期名称服务注册方法同一个范围新范围
暂时(Transient)AddTransient新实例新实例
范围内(Scoped)AddScoped同一个实例新实例
单例(Singleton)AddSingleton同一个实例同一个实例

4.服务注册方法

以下任何服务注册方法都可用于注册同一服务类型的多个实现。

方法自动
对象
释放
多种
实现
传递参数
Add{LIFETIME}<{SERVICE}, {IMPLEMENTATION}>()
示例:
services.AddSingleton<IMyDep, MyDep>();
Add{LIFETIME}<{SERVICE}>(sp => new {IMPLEMENTATION})
示例:
services.AddSingleton<IMyDep>(sp => new MyDep());
services.AddSingleton<IMyDep>(sp => new MyDep(99));
Add{LIFETIME}<{IMPLEMENTATION}>()
示例:
services.AddSingleton<MyDep>();
AddSingleton<{SERVICE}>(new {IMPLEMENTATION})
示例:
services.AddSingleton<IMyDep>(new MyDep());
services.AddSingleton<IMyDep>(new MyDep(99));
AddSingleton(new {IMPLEMENTATION})
示例:
services.AddSingleton(new MyDep());
services.AddSingleton(new MyDep(99));

MyService 定义两个构造函数参数:一个是 IMyDependency,另一个是 IEnumerable<IMyDependency>

当使用 IMyDependency 类型调用时,第二个AddSingleton会重写第一个AddSingleton,所以 IMyDependency 是已注册的最后一个实现。

当使用 IEnumerable<IMyDependency> 类型调用时,第二个AddSingleton会添加到第一个AddSingleton,所以IEnumerable<IMyDependency> 表示所有已注册的实现。通过 IEnumerable<{SERVICE}> 解析服务时,服务按其注册顺序显示。

services.AddSingleton<IMyDependency, MyDependency>();
services.AddSingleton<IMyDependency, DifferentDependency>();

public class MyService
{
    public MyService(IMyDependency myDependency, 
       IEnumerable<IMyDependency> myDependencies)
    {
        Trace.Assert(myDependency is DifferentDependency);

        var dependencyArray = myDependencies.ToArray();
        Trace.Assert(dependencyArray[0] is MyDependency);
        Trace.Assert(dependencyArray[1] is DifferentDependency);
    }
}

5.在应用启动时限时解析范围内服务

var builder = WebApplication.CreateBuilder(args);

builder.Services.AddScoped<IMyDependency, MyDependency>();

var app = builder.Build();

using (var serviceScope = app.Services.CreateScope())
{
    var services = serviceScope.ServiceProvider;

    var myDependency = services.GetRequiredService<IMyDependency>();
    myDependency.WriteMessage("Call services from main");
}

app.MapGet("/", () => "Hello World!");

app.Run();

6.框架提供的服务

下表列出了框架提供的服务的一小部分:

服务类型生存期
Microsoft.Extensions.DependencyInjection.IServiceScopeFactory单例
Microsoft.AspNetCore.Hosting.Builder.IApplicationBuilderFactory暂时
IHostApplicationLifetime单例
IWebHostEnvironment单例
Microsoft.AspNetCore.Hosting.IStartup单例
Microsoft.AspNetCore.Hosting.IStartupFilter暂时
Microsoft.AspNetCore.Hosting.Server.IServer单例
Microsoft.AspNetCore.Http.IHttpContextFactory暂时
Microsoft.Extensions.Logging.ILogger<TCategoryName>单例
Microsoft.Extensions.Logging.ILoggerFactory单例
Microsoft.Extensions.ObjectPool.ObjectPoolProvider单例
Microsoft.Extensions.Options.IConfigureOptions<TOptions>暂时
Microsoft.Extensions.Options.IOptions<TOptions>单例
System.Diagnostics.DiagnosticSource单例
System.Diagnostics.DiagnosticListener单例

原创文章,作者:huoxiaoqiang,如若转载,请注明出处:https://www.huoxiaoqiang.com/csharp/aspnetcoremvc/14602.html

(0)
上一篇 2022年4月4日 00:17
下一篇 2022年5月2日 01:17

相关推荐

  • 8.ASP.NET Core MVC标记帮助程序

    1.标记帮助程序 1.1@addTagHelper指令 @addTagHelper 指令指定程序集中要加载的标记帮助程序对于 Views 目录或子目录中的所有视图文件均可用。 @addTagHelper 后第一个参数指定程序集中要加载的的标记帮助程序的范围,第二个参数指定包含标记帮助程序的程序集。 …

  • 3.ASP.NET Core MVC配置

    1.配置提供程序 配置提供程序从配置源的键值对读取配置数据。 配置提供程序 配置源 Azure Key Vault 配置提供程序 Azure Key Vault Azure 应用配置提供程序 Azure 应用程序配置 命令行配置提供程序 命令行参数 无前缀环境变量配置提供程序 无前缀环境变量 (带前缀)环境变量配置提供…

  • 2.ASP.NET Core MVC中间件

    按照惯例,通过调用 Use 、Map、Run 扩展方法,向请求处理管道添加中间件组件。 请求管道中的每个中间件组件负责调用管道中的下一个组件,或使管道短路。当中间件短路时,它被称为“终端(terminal)中间件”,因为它阻止中间件进一步处理请求。 1.中间件顺序 2.Endpoint中间件 3.内置中间件 Middl…

发表回复

登录后才能评论