asp.net core 2.1依赖注入

时间:2019-02-28 15:23:40

标签: asp.net-core dependency-injection

在asp.net核心2.1 MVC应用程序中,我有以下代码来自掘金的Github,还有我自己做的一些附加工作:

    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;
    }

所以您可以看到它正在使用依赖项注入,但是我在问自己一些问题:

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中使用依赖注入的某种方式?

4)如果对问题3回答“是”,可以这样做吗?

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 个答案:

答案 0 :(得分:2)

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

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

  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容器来实例化对象时,才考虑使用第一种方法。