首页
学习
活动
专区
工具
TVP
发布
社区首页 >问答首页 >asp.net核心2.1依赖注入

asp.net核心2.1依赖注入
EN

Stack Overflow用户
提问于 2019-02-28 23:23:40
回答 1查看 489关注 0票数 2

在asp.net Core2.1MVC应用程序中,我有以下代码,这些代码来自于Github,来自于一个块,还有一些由我自己添加的代码:

代码语言:javascript
复制
    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)这两者有什么区别吗?

代码语言:javascript
复制
services.AddTransient<ILicenseStore<LicenseEntity>>(x => new LicenseStore<LicenseEntity>(dbOptions.DbType, dbOptions.ConnectionString));

代码语言:javascript
复制
services.AddTransient<ILicenseStore<LicenseEntity>>(new LicenseStore<LicenseEntity>(dbOptions.DbType, dbOptions.ConnectionString));

3)在队列中

代码语言:javascript
复制
services.AddTransient((Func<IServiceProvider, IUserStore<TUser>>)(x => new UserStore<TUser, TRole>(userCollection, roleCollection, x.GetService<ILookupNormalizer>())));

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

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

代码语言:javascript
复制
services.AddSingletion<IMongoClient>(new MongoClient("connectionString"));
services.AddTransient<IXStore>(new XStore(x.GetService<IMongoClient>()))

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

5)两者的区别是什么:

代码语言:javascript
复制
services.AddScoped((Func<IServiceProvider, IUserStore<TUser>>)(x => new UserStore<TUser, TRole>(x.GetRequiredService<IIdentityUserCollection<TUser>>(), x.GetRequiredService<IIdentityRoleCollection<TRole>>(), x.GetService<ILookupNormalizer>())));

代码语言:javascript
复制
services.AddScoped<IUserStore<TUser>, UserStore<TUser, TRole>>();

非常感谢您的回答:)

编辑:

新方法:

代码语言:javascript
复制
        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>>()));
EN

回答 1

Stack Overflow用户

发布于 2019-03-01 04:24:05

  1. 首先,userCollectionroleCollection只实例化一次。由于以下原因,这两个局部变量都不会被垃圾回收。它们由使用GC root.
  2. Yes,创建的委托(x => userCollectionx => roleCollection)捕获,并将委托添加到服务集合中,这绝对是lambda存在的集合。第一行编译,后一行不编译。你只能将构造的对象传递给AddSingletonservices.AddSingleton(x => new object)services.AddSingleton(new object)之间的唯一区别是当对象被实例化时,现在(new object)或者在第一次请求指定的服务类型时修复第二行

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

那么答案是肯定的。实际上,DI容器会为你做这件事,为每个构造函数参数调用GetService。因此,以下代码等同于您的代码

services.AddTransient<IXStore, XStore>()

  • Basically services.AddSingletion<IMongoClient>(new MongoClient("connectionString"));这两个例子是一样的。当您使用第一个示例时,您将使用DI容器手动解析所有构造函数参数。当您使用第二个构造器时,DI容器会自动为您解析所有构造函数参数。所以在这种情况下更倾向于第二种方法,因为它的代码更少。仅当您需要使用new自己实例化对象或为它们提供一些其他服务而不是通过DI容器实例化对象时,才考虑使用第一种方法。
票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/54929014

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档