在对象构建过程中引用尚未构建的服务。 C#

huangapple go评论62阅读模式
英文:

Reference a service in object construction before the service is built. C#

问题

builder.Services.AddSingleton<RunningGameService>();

builder.Services.AddAuthorization(options =>
{
    options.AddPolicy("GameGroupsAuthorisationConnect", policy =>
    {
        policy.Requirements.Add(new GameGroupsAuthorisationConnectRequirement());
    });
});
Hi,
我遇到的问题是,GameGroupsAuthorisationConnectRequirement 依赖于 RunningGameService,因此需要在构造函数中引用它。

对此我感到有些困惑。
提前感谢。
英文:
builder.Services.AddSingleton&lt;RunningGameService&gt;(); 

builder.Services.AddAuthorization(options =&gt;
{
    options.AddPolicy(&quot;GameGroupsAuthorisationConnect&quot;, policy =&gt;
    {
        policy.Requirements.Add(new GameGroupsAuthorisationConnectRequirement());
    });
});

Hi,
The problem I have is that the GameGroupsAuthorisationConnectRequirement is dependent on RunningGameService, and hence it requires a reference to it in the constructor.

I'm a tad lost with this.
Thanks in advance.

答案1

得分: 2

要求不应依赖于服务;它只是定义了适用于授权的参数。

来自文档

授权要求是一组数据参数,策略可以使用它们来评估当前用户主体。

例如:

public class GameGroupsAuthorisationConnectRequirement : IAuthorizationRequirement
{ 
    // 如果适用,可以添加属性。
}

处理该要求的是相应的AuthorizationHandler,该处理程序可以注入服务。

public class GameGroupsAuthorisationConnectRequirementHandler  
    : AuthorizationHandler<GameGroupsAuthorisationConnectRequirement>
{
    public GameGroupsAuthorisationConnectRequirementHandler(
        RunningGameService runningGameService
        /* 在此注入其他服务 */ 
        )
    { 
        // ...
    } 

    protected override Task HandleRequirementAsync(
        AuthorizationHandlerContext context, GameGroupsAuthorisationConnectRequirement requirement
        )
    {
        // ...
        
        context.Succeed(requirement);
        
        return Task.CompletedTask;
    }
}

注册该处理程序如下。这样做可以从 DI 容器中解析其服务。

builder.Services.AddSingleton<IAuthorizationHandler, GameGroupsAuthorisationConnectRequirementHandler>();

参见ASP.NET Core 中要求处理程序中的依赖注入

您定义策略的方式可以保持不变。

options.AddPolicy("GameGroupsAuthorisationConnect", policy =>
{
    policy.Requirements.Add(new GameGroupsAuthorisationConnectRequirement());
});
英文:

A requirement should not depend on a service; it just defines the parameters that are applicable for the authorization.

From the documentation

> An authorization requirement is a collection of data parameters that a policy can use to evaluate the current user principal.

For example

public class GameGroupsAuthorisationConnectRequirement : IAuthorizationRequirement
{ 
    // Any properties in case applicable.
}

It is the accompanying AuthorizationHandler that deals with the requirement that can have services injected.

public class GameGroupsAuthorisationConnectRequirementHandler  
    : AuthorizationHandler&lt;GameGroupsAuthorisationConnectRequirement&gt;
{
    public GameGroupsAuthorisationConnectRequirementHandler(
        RunningGameService runningGameService
        /* Inject other services here */ 
        )
    { 
        // ...
    } 

    protected override Task HandleRequirementAsync(
        AuthorizationHandlerContext context, GameGroupsAuthorisationConnectRequirement requirement
        )
    {
        // ...
        
        context.Succeed(requirement);
        
        return Task.CompletedTask;
    }
}

That handler gets registered as below. Doing so it gets its services resolved from the DI container.

builder.Services.AddSingleton&lt;IAuthorizationHandler, GameGroupsAuthorisationConnectRequirementHandler&gt;();

See Dependency injection in requirement handlers in ASP.NET Core.

The way you defined your policy can stay as-is.

options.AddPolicy(&quot;GameGroupsAuthorisationConnect&quot;, policy =&gt;
{
    policy.Requirements.Add(new GameGroupsAuthorisationConnectRequirement());
});

答案2

得分: 1

使用接受实例而不是泛型参数的 AddSingleton 重载,就像这样:

// 显然,您需要在这里满足此服务的所需构造函数参数...
var rgService = new RunningGameService(...); 
builder.Services.AddSingleton<RunningGameService>(rgService); 

builder.Services.AddAuthorization(options =>
{
    options.AddPolicy("GameGroupsAuthorisationConnect", policy =>
    {
        policy.Requirements.Add(new GameGroupsAuthorisationConnectRequirement(rgService));
    });
});
英文:

Use an overload of AddSingleton that accepts an instance instead of a generic parameter, like this:

// Obviously you need to satisfy _this_ service&#39;s required constructor params here...
var rgService = new RunningGameService(...); 
builder.Services.AddSingleton&lt;RunningGameService&gt;(rgService); 

builder.Services.AddAuthorization(options =&gt;
{
    options.AddPolicy(&quot;GameGroupsAuthorisationConnect&quot;, policy =&gt;
    {
        policy.Requirements.Add(new GameGroupsAuthorisationConnectRequirement(rgService));
    });
});

huangapple
  • 本文由 发表于 2023年3月7日 05:01:04
  • 转载请务必保留本文链接:https://go.coder-hub.com/75655811.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定