asp.net-core - asp.net core 2.1 依赖注入(inject)

标签 asp.net-core dependency-injection

在 asp.net core 2.1 MVC 应用程序中,我有以下代码,部分来自 Github 上的一个 block ,以及我所做的一些添加:

    public static IServiceCollection AddIdentityMongoDbProvider<TUser, TRole>(this IServiceCollection services, Action<IdentityOptions> setupIdentityAction, Action<MongoIdentityOptions> setupDatabaseAction) where TUser : UserEntity where TRole : RoleEntity
    {
        services.AddIdentity<TUser, TRole>(setupIdentityAction ?? (x => { }))
            .AddRoleStore<RoleStore<TRole>>()
            .AddUserStore<UserStore<TUser, TRole>>()
            .AddDefaultTokenProviders();

        var dbOptions = new MongoIdentityOptions();
        setupDatabaseAction(dbOptions);

        var userCollection = new IdentityUserCollection<TUser>(dbOptions.DbType, dbOptions.ConnectionString);
        var roleCollection = new IdentityRoleCollection<TRole>(dbOptions.DbType, dbOptions.ConnectionString);

        // Add collections and stores in services for DI
        services.AddTransient<IIdentityUserCollection<TUser>>(x => userCollection);
        services.AddTransient<IIdentityRoleCollection<TRole>>(x => roleCollection);

        services.AddTransient<ITenantStore<TenantEntity, TUser>>(x => new TenantStore<TenantEntity, TUser>(dbOptions.DbType, dbOptions.ConnectionString, userCollection));
        services.AddTransient<ILicenseStore<LicenseEntity>>(x => new LicenseStore<LicenseEntity>(dbOptions.DbType, dbOptions.ConnectionString));

        // Identity Services
        services.AddTransient((Func<IServiceProvider, IUserStore<TUser>>)(x => new UserStore<TUser, TRole>(userCollection, roleCollection, x.GetService<ILookupNormalizer>())));
        services.AddTransient<IRoleStore<TRole>>(x => new RoleStore<TRole>(roleCollection));

        return services;
    }

正如您所看到的,它使用依赖注入(inject),但我问自己一些问题:

1) userCollection 和 roleCollection 是“本地”变量,然后传递到 DI 中。那么这些对象的生命周期是如何管理的呢?我的意思是它们从未被丢弃,因为它们被用于 DI 中?或者他们每次都在创造?

2)有什么区别

services.AddTransient<ILicenseStore<LicenseEntity>>(x => new LicenseStore<LicenseEntity>(dbOptions.DbType, dbOptions.ConnectionString));

还有

services.AddTransient<ILicenseStore<LicenseEntity>>(new LicenseStore<LicenseEntity>(dbOptions.DbType, dbOptions.ConnectionString));

3)在行中

services.AddTransient((Func<IServiceProvider, IUserStore<TUser>>)(x => new UserStore<TUser, TRole>(userCollection, roleCollection, x.GetService<ILookupNormalizer>())));

有“x.GetService()”。这是一种告诉构造函数构造函数中所需的参数将来自 DI 的方法吗?有点像在 DependecyInjection 中使用依赖注入(inject)?

4)如果问题3为"is",是否可以做这样的事情?

services.AddSingletion<IMongoClient>(new MongoClient("connectionString"));
services.AddTransient<IXStore>(new XStore(x.GetService<IMongoClient>()))

重点是要实现 MongoClient 将是单例(这是推荐的方式)

5)两者之间有什么区别:

services.AddScoped((Func<IServiceProvider, IUserStore<TUser>>)(x => new UserStore<TUser, TRole>(x.GetRequiredService<IIdentityUserCollection<TUser>>(), x.GetRequiredService<IIdentityRoleCollection<TRole>>(), x.GetService<ILookupNormalizer>())));

还有

services.AddScoped<IUserStore<TUser>, UserStore<TUser, TRole>>();

非常感谢您的回答:)

编辑:

新方法:

        services.AddSingleton<ICustomMongoClient>(x => new CustomMongoClient(dbOptions.ConnectionString));

        // Add collections and stores in services for DI
        services.AddTransient<IIdentityUserCollection<TUser>>(x => new IdentityUserCollection<TUser>(x.GetRequiredService<ICustomMongoClient>()));
        services.AddTransient<IIdentityRoleCollection<TRole>>(x => new IdentityRoleCollection<TRole>(x.GetRequiredService<ICustomMongoClient>()));


        services.AddTransient<ITenantStore<TenantEntity, TUser>>(x => new TenantStore<TenantEntity, TUser>(x.GetRequiredService<ICustomMongoClient>(), x.GetRequiredService<IIdentityUserCollection<TUser>>()));
        services.AddTransient<ILicenseStore<LicenseEntity>>(x => new LicenseStore<LicenseEntity>(x.GetRequiredService<ICustomMongoClient>()));

        // Identity Services
        services.AddTransient((Func<IServiceProvider, IUserStore<TUser>>)(x => new UserStore<TUser, TRole>(x.GetRequiredService<IIdentityUserCollection<TUser>>(), x.GetRequiredService<IIdentityRoleCollection<TRole>>(), x.GetService<ILookupNormalizer>())));
        services.AddTransient<IRoleStore<TRole>>(x => new RoleStore<TRole>(x.GetRequiredService<IIdentityRoleCollection<TRole>>()));

最佳答案

  1. 首先userCollectionroleCollection仅实例化一次。由于以下原因,这两个局部变量都不会被垃圾收集。它们由使用 lambda( x => userCollectionx => roleCollection )创建的委托(delegate)捕获,并且委托(delegate)被添加到服务集合中,这绝对是 GC root 。 .

  2. 是的,有。第一行可以编译,后一行则不能。您只能将构造对象传递给 AddSingletonservices.AddSingleton(x => new object) 之间唯一的区别和services.AddSingleton(new object)是在实例化对象时,立即 ( new object ) 或在第一次请求指定服务类型时 ( x => new object )。

  3. 是的。

  4. 如果修复第二行
    services.AddSingletion<IMongoClient>(new MongoClient("connectionString")); services.AddTransient<IXStore>(x => new XStore(x.GetService<IMongoClient>()))
    那么答案是。事实上DI容器会为你做这件事,调用 GetService对于每个构造函数参数。所以下面的代码相当于你的
    services.AddSingletion<IMongoClient>(new MongoClient("connectionString")); services.AddTransient<IXStore, XStore>()

  5. 基本上这两个示例是相同的。当您使用第一个示例时,您可以使用 DI 手动解析所有构造函数参数。容器。当您使用第二个时 DI容器会自动为您解析所有构造函数参数。因此在这种情况下更喜欢第二种方法,因为它的代码更少。仅当您需要使用new自己实例化对象时才考虑使用第一种方法或为他们提供一些其他服务而不是DI容器。

关于asp.net-core - asp.net core 2.1 依赖注入(inject),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/54929014/

相关文章:

c# - 是否可以在.net core中重定向来自中间件的请求

c# - ASP.NET Core 2.0 预览版 1 : How to set up Cookie Authentication with custom login path

java - 非 Activity Java 类中的 Dagger 2 注入(inject)

symfony - 如何在 Symfony 5 迁移中使用容器(和服务)?

android - 如何在考虑测试的情况下使用 Dagger 设计 Android 应用程序

c# - 与日志注入(inject)模块一起使用时在 Autofac 中显式解析 ILog

asp.net-core - 包 Microsoft.AspNetCore.Authentication.JwtBearer 5.0.0 与 netcoreapp3.1 不兼容,但它的目标是 net 5.0

forms - 多部分/表单数据 ASP.NET Core 6 后端 - 415 不支持的媒体类型

c# - 手动将 url 与 .NET Core 3.0 中的注册端点匹配

c# - 关于DI的问题以及如何解决一些问题