【问题标题】:Autofac: How to use per request dependency in the SingleInstance scope?Autofac:如何在 SingleInstance 范围内使用每个请求的依赖关系?
【发布时间】:2018-07-23 09:05:22
【问题描述】:

IDbConnection连接依赖注册为per-requestApplicationOAuthProvider注册为single instance

builder.Register(c => new SqlConnection(WebConfigUtils.DefaultConnectionString))
            .As<IDbConnection>()
            .InstancePerRequest();

builder.RegisterType<ApplicationOAuthProvider>()
            .As<IOAuthAuthorizationServerProvider>()
            .PropertiesAutowired()
            .SingleInstance();

需要在身份声明中存储用户权限。为此,我创建了命令 GetRolePermissions,并在此命令中注入 IDbConnection 实例。

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

这个命令正在ApplicationOAuthProvider中创建

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 需要注入IDbConnection,但当前ApplicationOAuthProvider 的autofac 范围是"root",并且在此范围内没有注册iDbConnection。但它存在于per-request 范围内。

不想将perLifettime 用于IDbConnection,因为我认为dbConnection 在不必要时应该关闭。我想这样做:

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

但无法使此解决方案发挥作用。而且我不知道如何正确获取容器,现在它是我手动设置的 AutofacConfig 的静态变量。

如何启用将IDbConnection 注入此GetPermissions.Handler

【问题讨论】:

    标签: c# asp.net-web-api dependency-injection asp.net-web-api2 autofac


    【解决方案1】:

    实际上,InstancePerLifetimeScope() 是您正在寻找的解决方案。您需要做的就是注入 DbConnection factory 来生成拥有的(docs link 1docs 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
            }
        }
    }
    

    它确实改变了请求范围的子范围的行为,但我不确定这是否对您的代码有问题 - 试一试,它应该可以正常工作。如果没有,那么你知道在哪里问。 ;)

    【讨论】:

    • 谢谢,在此之后,我将阅读更多文档并实施更多示例,以便更好地理解 autofac 和 DI 的共同点。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-04-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多