How to use a class (instead of a Blazor Component) with an injected service in another class?

92 views Asked by At

I have a lookup service in a blazor hybrid application that essentially gets entities from database. Have registered this in main as

AddScoped<ILookupService, LookupService>

Throughout the application have been using this service without any issues in components.

Now I have come to a point where I want to perform form validations. I wish to get some constant values from database and use these to write some custom validation attributes.

I have created a class BusinessConstants

public class BusinessConstantsLookup
{
    private ILookupService _lookupService;

    public BusinessConstantsLookup(ILookupService lookupService)
    {
        _lookupService = lookupService;
    }

    public string GetBusinessConstant(string businessConstantName)
    {
        ...
    }
}

Have also registered this as scoped.

Now is there a way to use this class in custom validation attribute class? The challenge is where do I get the instance for LookupService to use in the BusinessConstantsLookup constructor when I use it in that custom validation attribute class.

public class CustomRangeAttribute : ValidationAttribute
{
    protected override ValidationResult IsValid(
        object? value, ValidationContext validationContext)
    {
        BusinessConstantsLookup businessConstantsLookup =
            new BusinessConstantsLookup(<how I get LookupService instance?>);
        ...
    }
}
1

There are 1 answers

0
teamol On

Can DI in attribute class be solution?

Let's consider about Dependency Injection and Attributes in .NET Core and C#:

  1. DI in C# mainly relies upon constructors to inject things into a new instance.
  2. Attributes in C# have limitation on their constructor parameters. Runtime instances generally cannot be used as an attribute's constructor parameter, for example.

Thus we can rule out injecting DbContext into an attribute. So, what can we do next?

Method 1. Get the constants from database, store them into a static class.


Your attribute can then access the static properties to get the db constants, but beware of potential issues:

  • You need to make sure that on application startup, said static properties will be populated. (The DbContext is then decoupled with your attribute, because the class populates it accesses DbContext instead.)
  • If database constants can be updated during online time, you need to handle the updating.
  • You need to handle cases where you're validating but the constants ain't populated at all.

The basic structure of this method

Method 2. Validate in services instead.


ValidationAttributes in C# usually are used for input validations. Write validations that rely upon database content in methods using the input objects, and the class of those methods can inject DbContext or classes which can access it.