2 votes

Comment enregistrer un ObjectPoolProvider générique dans DI ?

Je lis artículo sur les pools d'objets. J'ai une politique de pool d'objets :

public class DictionaryPolicy<TKey, TValue> : PooledObjectPolicy<Dictionary<TKey, TValue>>
{
    public override Dictionary<TKey, TValue> Create()
    {
        return new Dictionary<TKey, TValue>();
    }

    public override bool Return(Dictionary<TKey, TValue> obj)
    {
        obj.Clear();

        return true;
    }
}

Et maintenant, je dois l'enregistrer.

services.AddSingleton(provider =>
     provider.GetRequiredService<ObjectPoolProvider>().Create(new DictionaryPolicy()));

Il y a une erreur de compilation parce que je dois définir des paramètres génériques pour DictionaryPolicy. Mais je ne veux pas enregistrer chaque dictionnaire avec le type spécifique que j'utilise. De plus, chaque pool d'un type de dictionnaire spécifique doit être enregistré en tant que singleton.

1voto

Rafal Points 5490

Je ne pense pas que cela soit possible avec la simple construction en DI dans asp.net mais c'est un cas d'utilisation parfaitement valide si vous utilisez Autofac DI. Si vous êtes prêt à l'utiliser en installant Autofac.Extensions.DependencyInjection nuget, vous devrez le configurer, de la manière la plus simple possible, en une seule ligne :

public static void Main(string[] args)
{
    var createMethod = typeof(ObjectPoolProvider).GetMethods().First(x => x.Name == "Create" && x.GetParameters().Length == 1);
    var builder = WebApplication.CreateBuilder(args);
    /*1*/builder.Host.UseServiceProviderFactory(new AutofacServiceProviderFactory());
    builder.Host.ConfigureContainer<ContainerBuilder>(
            builder =>
            {
                /*2*/builder.RegisterGeneric(typeof(DictionaryPolicy<,>))
                               .As(typeof(PooledObjectPolicy<>))
                               .SingleInstance();
                builder.RegisterType<DefaultObjectPoolProvider>().As<ObjectPoolProvider>().SingleInstance();
                /*3*/builder.RegisterGeneric((c, t) =>
                {
                    var provider = c.Resolve<ObjectPoolProvider>();
                    var policy = c.Resolve(typeof(PooledObjectPolicy<>).MakeGenericType(t[0]));                        
                    return createMethod.MakeGenericMethod(t[0]).Invoke(provider, new object[] { policy })!;

                }).As(typeof(ObjectPool<>)).SingleInstance();
            }
       );
    builder.Services.AddControllers();

appeler à UseServiceProviderFactory configure Autofac en tant que DI ; La deuxième ligne enregistre votre implémentation de politique personnalisée en tant que classe de base. PooledObjectPolicy . Enfin une usine sur mesure pour ObjectPool qui fait essentiellement la même chose que dans l'article que vous avez posté avec un peu de réflexion.

Pour vérifier que vous pouvez exécuter n'importe quelle action du contrôleur :

enter image description here

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X