Drago
Drago

Reputation: 1875

Injecting a dependency to constructor of an attribute in C#

I have the following attribute:

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

And the following class which has a method I use the attribute on.

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

Now I get a problem when I use the MultipleInteractivities as attribute above the Apply method. It expects me to pass an argument to its constructor.

Now since I already inject IInteractivityService in the constructor of the RecruitmentModule class. I try to pass it as an argument to my MultipleInteractivities attribute.

Like this:

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

However, this gives the following error:

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

So I try to make _interactivityService field static in the RecruitmentModule class like this:

private static IInteractivityService _interactivityService;

Now I get the following error when it is passed as an argument to my MultipleInteractivities attributes.

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

How can I get IInteractivityService passed to my MultipleInteractivitiesAttribute without getting errors.

Upvotes: 0

Views: 476

Answers (1)

devNull
devNull

Reputation: 4219

You don't need to (and shouldn't) inject the dependency into the attribute constructor. Instead, the CommandContext has a Services property returning an IServiceProvider that you can use to resolve the dependency:

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

Upvotes: 2

Related Questions