• Asp.net core 学习笔记 ( DI 依赖注入 )


    更新: 2021-06-29

    什么时候用 singleton, scope, transient 

    https://stackoverflow.com/questions/38138100/addtransient-addscoped-and-addsingleton-services-differences

    更新: 2021-06-22

    如果我们多次 AddScope 

    services.AddScoped<Person, Ali>();
    services.AddScoped<Person, Mudu>();

    注入的时候可以拿到 list 哦, 顺序就是看哪一个后注册咯

    Person mudu,
    IEnumerable<Person> muduAndAli

    identity 的 UserValidator 就用了这个方式

    更新 2020-01-11

    动态创建 class 并且可以使用 DI, 这样反射样就可以了

    var instance = ActivatorUtilities.CreateInstance<AbcService>(serviceProvider);

    更新 2019-05-06 

    用泛型来传 class, 这样比较方便扩展

    services.AddEmail<EmailService>();
    services.AddEmail<NewEmailService>();

    AddEmail 

    public static class ServiceCollectionExtensions
    {
        public static IServiceCollection AddEmail<TEmailService>(
            this IServiceCollection services
        )
        where TEmailService : IEmailService
        {
            services.AddScoped(typeof(IEmailService), typeof(TEmailService));
            return services;
        }
    }
    
    public interface IEmailService
    {
        string GetValue();
    }
    
    public class EmailService : IEmailService
    {
        public string GetValue()
        {
            return "email v1";
        }
    }
    
    public class NewEmailService : IEmailService
    {
        public string GetValue()
        {
            return "email v2";
        }
    }

    比起 Angular 的依赖注入, core 的相对简单许多, 容易明白 

    所有 provider 都在 startup 里配置. 

    public void ConfigureServices(IServiceCollection services)
    {
        services.Configure<Business>(Configuration.GetSection("business"));
        services.Configure<Configuration.Email>(Configuration.GetSection("email"));
    
        services.AddEmail();
        // Razor template 
        services.AddSingleton<ICompositeViewEngine, CompositeViewEngine>();
        services.AddSingleton<IActionContextAccessor, ActionContextAccessor>();
    
        // Entity 
        services.AddScoped(_ => new DB(Configuration.GetConnectionString("DefaultConnection")));
    
        // hangfire
        services.AddHangfire(config =>
                config.UseSqlServerStorage(Configuration.GetConnectionString("DefaultConnection")));
    
        // MVC
        services.Configure<RazorViewEngineOptions>(options =>
        {
            options.ViewLocationExpanders.Add(new FeatureLocationExpander());
        });
        services.AddMvc();
    }

    controller 就通过 constructor 来注入就可以了. 

    private readonly DB db;
    private ICompositeViewEngine CompositeViewEngine { get; set; }
    private ActionContext ActionContext { get; set; }
    private IServiceProvider ServiceProvider { get; set; }
    private ITempDataProvider TempDataProvider { get; set; }
    private Configuration.Email EmailConfig { get; set; }
    
    public DebugController(
        DB db,
        ICompositeViewEngine compositeViewEngine,
        IActionContextAccessor actionContextAccessor,
        IServiceProvider serviceProvider,
        ITempDataProvider tempDataProvider,
        IOptionsSnapshot<Configuration.Email> emailOptionsAccessor
    )
    {
        CompositeViewEngine = compositeViewEngine;
        ActionContext = actionContextAccessor.ActionContext;
        ServiceProvider = serviceProvider;
        TempDataProvider = tempDataProvider;
        EmailConfig = emailOptionsAccessor.Value;
        this.db = db;
    }

    provider 有 3 个级别 

    AddSingleton

    AddScoped

    AddTransient

    单列是说整个 App 用一个实例

    Scope 一个 request 一个实例

    transient 则是每一个注入一个实例

    一个模块一般上会提供好多 Service 

    那么要让 startup 干净一些的话,我们可以包装起来 

    就好像这样  services.AddEmail();

    做法是开一个扩展方法 

    namespace Project.Email
    {
        public static class ServiceCollectionExtensions
        {
            public static IServiceCollection AddEmail(
                this IServiceCollection services)
            {
                services.AddSingleton<ICompositeViewEngine, CompositeViewEngine>();
                services.AddSingleton<IActionContextAccessor, ActionContextAccessor>();
                services.AddScoped<EmailService, EmailService>();
                return services;
            }
        }
    
        public class EmailService
        {
            public EmailService()
            {
    
    
            }
    
            public string name { get; set; } = "dada";
        }
    }
  • 相关阅读:
    jQuery on注册事件
    前端表格(Table)多条数据可以增加行删除行json封装后Post数据到后台处理
    导出Excel数据
    C#在一个实体类上新加字段并把另外一个实体类的字段值赋给它
    函数(五)-内置函数
    函数(四)-命名空间与作用域
    函数(三)-return与函数的调用
    函数(二)- 参数
    函数(一)-基本格式
    字符串格式化
  • 原文地址:https://www.cnblogs.com/keatkeat/p/7742543.html
Copyright © 2020-2023  润新知