How to register dependency injection with generic types? (.net core)

21,316

Solution 1

You can use services.AddScoped to use only 1 instance in the scope request. So in general improvement compare to AddTransient

services.AddScoped(typeof(IGenericRepository<>), typeof(GenericRepository<>));

So my interface and class will look like this

public interface IGenericRepository<T> where T : class
public class GenericRepository<T> : IGenericRepository<T> where T : class

Solution 2

As stated in the comments you should set the generic constraint to where T: class in order to satisfy the constraint of the AddSingleton call.

Reference AddSingleton(IServiceCollection, TService)

Additionally you can bind the object graph using ConfigurationBinder.Get<T>

Reference Configuration in ASP.NET Core : Bind to an object graph

ConfigurationBinder.Get<T> binds and returns the specified type. Get<T> is more convenient than using Bind.

like in the following example

public static class IServiceCollectionExtensions {
    public static IServiceCollection AddSingletonConfigurationObject<TService>(
        this IServiceCollection services, 
        IConfiguration configuration,
        string appSettingsKey) where TService: class
    {   

        var setting = configuration.GetSection(appSettingsKey).Get<TService>();
        services.AddSingleton(setting);
        return services;
    }
}

Solution 3

I was able to use this style to encapsulate (as an extension method)

using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.DependencyInjection.Extensions;

namespace MyProject.DependencyInjection
{
    public static class MyEncapsulatedIocRegistration
    {
        public static IServiceCollection AddTypeT<T>(this IServiceCollection services) where T : class
        {
            services.AddSingleton<IMyThingInterface<T>, MyThingConcrete<T>>();

            return services;
        }
    }
}
Share:
21,316
Rémy
Author by

Rémy

Updated on July 09, 2022

Comments

  • Rémy
    Rémy almost 2 years

    I have an asp.net core web app with multiple parameters in appSettings.json file.

    I didnt' want to have services having IOptions<MyObject> in the constructor.

    I wanted MyObject in the constructor. So I found the following article: https://weblog.west-wind.com/posts/2017/dec/12/easy-configuration-binding-in-aspnet-core-revisited which is very interesting.

    But I want to go further. I would like to create an extension method to generate the injection.

    Here is what I would like to do:

    using Microsoft.Extensions.Configuration;
    using Microsoft.Extensions.DependencyInjection;
    
    namespace Common.WebTools.Extensions
    {
        public static class IServiceCollectionExtensions
        {
            public static IServiceCollection AddSingletonConfigurationObject<T>(this IServiceCollection services, 
                IConfiguration configuration,
                string appSettingsKey) where T:new()
            {   
                var obj2 = new T();
                configuration.Bind(appSettingsKey, obj);
                services.AddSingleton(obj2); //compilation failed
                return services;
            }
        }
    }
    

    And then in my ConfigureServices method I can call

    services.AddSingletonConfigurationObject<Common.Tools.Configuration.GoogleAnalyticsConfiguration>(Configuration, "GoogleAnalytics");
    

    But I Have a compliation error on this line:

    services.AddSingleton(obj2); 
    

    Does somebody know how could I correct the error?

  • AMG
    AMG about 4 years
    So how would the target for the injected instance actually look?
  • AMG
    AMG about 4 years
    Is it even possible with constructor injecton since it requires a type argument? private readonly IGenericRepository<???> _repository;
  • mRizvandi
    mRizvandi about 3 years
    private readonly IGenericRepository<T> GenericRepository; ....... in the constructor parameters use ....IGenericRepository<T> genericRepository; and in body of constructor set the property .... GenericRepository = genericRepository. you have to use it in generic class, with same T inheritance.
  • Patrick Szalapski
    Patrick Szalapski over 2 years
    Any idea why this idea can't work with AddTransient?