1
votes

Obtenez une dépendance en cas de besoin?

Existe-t-il un moyen d'obtenir / de récupérer des dépendances uniquement lorsque cela est nécessaire?

public class DependentClass
{
    public DependentClass(IMandatoryDependency mandatoryDependency)
    {
        // Assigned to class level property
    }

    public void MethodsOne()
    {
        mandatoryDependency.CallMandatoryMethod();
        DIContainer.GetDependency<IDependency1>().CallDependecy1Method();
    }

    public void MethodsTwo()
    {
        mandatoryDependency.CallMandatoryMethod();
        DIContainer.GetDependency<IDependency2>().CallDependecy2Method();
    }

    public void MethodsOne()
    {
        mandatoryDependency.CallMandatoryMethod();
        DIContainer.GetDependency<IDependency3>().CallDependecy3Method();
    }
}

À partir de l'extrait de code ci-dessus, je voudrais obtenir la dépendance des méthodes individuelles lorsque je suis dans les méthodes lui-même. Quelque chose comme ceci:

public class DependentClass
{
    public DependentClass(IMandatoryDependency mandatoryDependency, IDependency1 dependency1, IDependency2 dependency2, IDependency3 dependency3)
    {
        // Assigned to class level property
    }

    public void MethodsOne()
    {
        mandatoryDependency.CallMandatoryMethod();
        dependency1.CallDependecy1Method();
    }

    public void MethodsTwo()
    {
        mandatoryDependency.CallMandatoryMethod();
        dependency2.CallDependecy2Method();
    }

    public void MethodsThree()
    {
        mandatoryDependency.CallMandatoryMethod();
        dependency3.CallDependecy3Method();
    }
}


1 commentaires

Vous pouvez résoudre à partir du conteneur DI dans la méthode oui, la plupart des frameworks DI vous permettent d'injecter le conteneur lui-même en tant que dépendance, cependant, la plupart du temps, il existe un meilleur modèle que vous pouvez utiliser pour des trucs comme celui-ci, quelle est la raison pour laquelle le dépendance injectée au point d'utilisation? Il semble que vous pourriez avoir intérêt à injecter une usine à la place ou à utiliser certaines des fonctionnalités de résolution les plus complexes. Quel conteneur DI utilisez-vous également?


3 Réponses :


3
votes

En supposant que vous utilisez un conteneur IOC, vous pouvez injecter une instance du conteneur lui-même dans le constructeur, puis utiliser cette instance pour résoudre vos services mauvais ce n'est pas une bonne pratique, vous pourriez chercher quelque chose comme ceci

Une autre bonne option serait de faire des dépendances optionnelles un objet Lazy, en utilisant simplement la classe Lazy, donc votre code sera Lazy

l'utilisation du modèle paresseux garantit que les objets ne sont pas instanciés à moins que vous ne souhaitiez réellement y accéder, vous pouvez en savoir plus à ce sujet ici


1 commentaires

Merci pour votre suggestion. C'est une bonne solution mais je trouve une réponse plus convaincante. @MostafaElite



1
votes

dans le noyau asp.net, nous pouvons injecter IServiceProvider dans le contrôleur et résoudre nous-mêmes les dépendances au moment de l'exécution comme:

public void MethodsOne()
{
    mandatoryDependency.CallMandatoryMethod();
    _serviceProvider.GetService(typeof(IDependency1)).CallDependecy1Method();
}

et dans la méthode, nous pouvons demander au fournisseur pour donner l'instance d'une dépendance particulière comme:

private IServiceProvider _serviceProvider;
private IMandatoryDependency _mandatoryDependency;
public DependentClass(IMandatoryDependency mandatoryDependency,
                      IServiceProvider serviceProvider)
{
    _serviceProvider = serviceProvider;
    _mandatoryDependency = mandatoryDependency;
}

Mais il n'est pas considéré comme une bonne idée d'injecter IServiceProvider voir:

Pourquoi ne pas injecter IServiceProvider au lieu de chaque dépendance individuelle? a>

Vous pouvez consulter plus de détails sur le service d'injection de dépendances en particulier dans le noyau asp.net à l'adresse suivante:

https://andrewlock.net/new-in-asp-net-core-3-service-provider-validation /

http: //www.b inaryintellect.net/articles/17ee0ba2-99bb-47f0-ab18-f4fc32f476f8.aspx

Lisez également les meilleures pratiques pour l'injection de dépendances dans le noyau asp.net:

https://medium.com/volosoft / asp-net-core-dependency-injection-best-practices-tips-tricks-c6e9c67f9d96


3 commentaires

Ce n'est pas mon vote négatif, mais c'est une mauvaise idée pour de nombreuses raisons. Vous ne mentionnez aucun inconvénient?


@CodeCaster Oui, il y a un inconvénient évident à passer au localisateur de services car nous pilotons nous-mêmes la résolution des dépendances au lieu de faire faire cela par le conteneur DI lui-même pour nous, mais c'est l'une des façons dont nous pouvons


@EhsanSajjad J'apprécie vos efforts mais cette solution n'est pas assez convaincante.



1
votes

Vous devez enregistrer les services en tant que Lazily dans StartUp.cs.

public void MethodsOne([FromServices] IDependency1 dependency1)
    {
        mandatoryDependency.CallMandatoryMethod();
        dependency1.CallDependecy1Method();
    }

Ensuite, dans votre Controller , utilisez la dépendance comme Lazy

public class DependentClass
{
    private readonly Lazy<IDependency1> _dependency1;
    public DependentClass(IMandatoryDependency mandatoryDependency, Lazy<IDependency1> dependency1)
    {
        // Assigned to class level property
        _dependency1 = dependency1;
    }

    public void MethodsOne()
    {
        mandatoryDependency.CallMandatoryMethod();
        _dependency1.Value.CallDependecy1Method();
    }
}

Si vous utilisez IDependency1 dans une seule méthode, vous pouvez donc résoudre la dépendance en utilisant FromServices dans .NET core au lieu d'injecter une dépendance dans le constructeur.

services.AddTransient<IDependecy1, Dependecy1>();
services.AddTransient(serviceProvider => new Lazy<IDependecy1>(() => serviceProvider.GetRequiredService<IDependecy1>()));


4 commentaires

La solution FromServices semble bonne. Je vais certainement essayer ceci et vous revenir là-dessus. @Vaudou


Oui, vous pouvez l'utiliser lorsque vous n'avez besoin du service qu'une seule fois.


Il semble que FromServices est supposé être utilisé uniquement dans le contrôleur et non dans d'autres endroits, sinon nous devons passer la dépendance en paramètre. Corrigez-moi si je me trompe. @Vaudou


Non, vous pouvez l'utiliser en méthode sans le passer, il suffit d'enregistrer le service dans Startup.cs et de l'utiliser sans le passer explicitement.