在 C# 中注入对属性构造函数的依赖

Injecting a dependency to constructor of an attribute in C#

我有以下属性:

public class MultipleInteractivitiesAttribute : CheckBaseAttribute
{
    private readonly IInteractivityService _interactivityService;

    public MultipleInteractivitiesAttribute(IInteractivityService interactivityService)
    {
        _interactivityService = interactivityService;
    }

    public override Task<bool> ExecuteCheckAsync(CommandContext ctx, bool help)
    {
        var userId = ctx.User.Id;
        var cmdName = ctx.Command.QualifiedName;

        return Task.FromResult(!_interactivityService.CheckForUserInteractivity(userId, cmdName));
    }
}

下面的 class 有一个我使用属性的方法。

public class RecruitmentModule : BaseCommandModule
{
    private readonly IInteractivityService _interactivityService;

    public RecruitmentModule(IInteractivityService interactivityService)
    {
        _interactivityService = interactivityService;
    }
    
    [Command("apply"), MultipleInteractivities()]
    public async Task Apply(CommandContext ctx)
    {
          // some code here
    }
}

现在,当我在 Apply 方法上方使用 MultipleInteractivities 作为属性时遇到问题。它希望我将参数传递给它的构造函数。

现在,因为我已经在 RecruitmentModule class 的构造函数中注入了 IInteractivityService。我尝试将其作为参数传递给我的 MultipleInteractivities 属性。

像这样:

[Command("apply"), MultipleInteractivities(_interactivityService)]

但是,这会产生以下错误:

Cannot access non-static field '_interactivityService' in static context

所以我尝试在 RecruitmentModule class 中使 _interactivityService 字段静态化,如下所示:

private static IInteractivityService _interactivityService;

现在,当它作为参数传递给我的 MultipleInteractivities 属性时,出现以下错误。

Attribute constructor parameter 'interactivityService' has type 'DiscordBot.Core.Interfaces.IInteractivityService', which is not a valid attribute parameter type

如何将 IInteractivityService 传递给我的 MultipleInteractivitiesAttribute 而不会出现错误。

您不需要(and shouldn't) inject the dependency into the attribute constructor. Instead, the CommandContext has a Services 属性 返回可用于解决依赖关系的 IServiceProvider

public class MultipleInteractivitiesAttribute : CheckBaseAttribute 
{ 
    public override Task<bool> ExecuteCheckAsync(CommandContext ctx, bool help) 
    { 
        var userId = ctx.User.Id; 
        var cmdName = ctx.Command.QualifiedName; 
        var interactivityService = ctx.Services.GetService<IInteractivityService>();

        return Task.FromResult(!interactivityService.CheckForUserInteractivity(userId, cmdName)); 
    } 
}