代码之家  ›  专栏  ›  技术社区  ›  Nikita

Autofac:如何在单实例作用域中使用每个请求依赖项?

  •  0
  • Nikita  · 技术社区  · 8 年前

    IDbConnection 连接依赖项注册为 per-request ApplicationOAuthProvider 注册为 single instance .

    builder.Register(c => new SqlConnection(WebConfigUtils.DefaultConnectionString))
                .As<IDbConnection>()
                .InstancePerRequest();
    
    builder.RegisterType<ApplicationOAuthProvider>()
                .As<IOAuthAuthorizationServerProvider>()
                .PropertiesAutowired()
                .SingleInstance();
    

    需要在标识声明中存储用户权限。为此,我创建了GetRolePermissions命令,并在该命令中插入 IDB连接 实例。

    public class GetRolePermissions
    {
        public class Command: IRequest<List<string>>
        {
            public ICollection<AspNetUserRole> UserRoles { get; set; }
        }
    
        public class Handler : AsyncRequestHandler<Command, List<string>>
        {
            private IDbConnection databaseConnection;
    
            public Handler(IDbConnection databaseConnection)
            {
                this.databaseConnection = databaseConnection;
            }
        }
    }
    

    此命令是在 应用程序身份验证提供程序

    public class ApplicationOAuthProvider : OAuthAuthorizationServerProvider
    {
        private async Task<ClaimsIdentity> GenerateUserIdentityAsync(AspNetUser user, string authenticationType)
        {
            user.SecurityStamp = Guid.NewGuid().ToString();
            var identity = await mediator.Send(new GenerateUserIdentity.Command
            {
                AuthenticationType = authenticationType,
                User = user
            });
    
            List<string> permissions = null;
            permissions = await mediator.Send(new GetRolePermissions.Command { UserRoles = user.Roles });
            var permissionClaimValue = permissions != null && permissions.Count > 0
                ? permissions.Aggregate((resultString, permission) => resultString + "," + permission)
                : "";
            identity.AddClaim(new Claim(AuthenticationConstants.Gender, user.Gender.ToString()));
            identity.AddClaim(new Claim(AuthenticationConstants.Permissions, permissionClaimValue));
            return identity;
        }
    }
    

    permissions = await mediator.Send(new GetRolePermissions.Command { UserRoles = user.Roles }); -将错误抛出为 GetRolePermissions.Handler 需要注射 IDB连接 ,但当前的autofac范围 应用程序身份验证提供程序 "root" 而且没有 iDbConnection 已在此范围内注册。但它存在于 按请求 范围。

    不想使用 perLifettime 因为我认为 dbConnection 应该在不必要时关闭我被认为是这样做的:

    using(var scope = AutofacConfig.container.BeginLifiTime("AutofacWebRequest")) 
    {
          permissions = await mediator.Send(new GetRolePermissions.Command { UserRoles = user.Roles });
    }
    

    但不能让这个解决方案起作用。我不知道如何正确地获取容器,目前它是AutofacConfig的静态变量,我手动设置的。

    如何启用注入 IDB连接 进入这个 GetPermissions.Handler ?

    1 回复  |  直到 8 年前
        1
  •  1
  •   Alexander Leonov    8 年前

    事实上, InstancePerLifetimeScope() 是你要找的解决方案。您只需要注入DbConnection 工厂 生产自有产品( docs link 1 docs link 2 )DbConnection的实例,而不是DbConnection本身。

    // registration
    
    builder.RegisterType<SqlConnection>()
        .As<IDbConnection>()
        .WithParameter(new NamedParameter("connectionString", WebConfigUtils.DefaultConnectionString))
        .InstancePerLifetimeScope();
    
    // usage
    
    public class GetRolePermissions
    {
        public class Command: IRequest<List<string>>
        {
            public ICollection<AspNetUserRole> UserRoles { get; set; }
        }
    
        public class Handler : AsyncRequestHandler<Command, List<string>>
        {
            private Func<Owned<IDbConnection>> _connectionFactory;
    
            public Handler(Func<Owned<IDbConnection>> connectionFactory)
            {
                _connectionFactory = connectionFactory;
            }
    
            // not really sure where your consuming code is, so just something off the top of my head
            public DontKnowYourResultType Handle(GetRolePermissions.Command cmd) {
                using (var ownedConnection = _connectionFactory()) {
                    // ownedConnection.Value is the DbConnection you want
                    // ... do your stuff with that connection
                } // and connection gets destroyed upon leaving "using" scope
            }
        }
    }
    

    它确实会更改请求作用域的子作用域的行为,但我不确定这是否是您的代码的问题-请尝试一下,它应该可以正常工作如果没有,你知道该问哪里。;)

    推荐文章