web-dev-qa-db-fra.com

ASP.NET Core DependencyResolver

Dans ASP.NET MVC 5, il est possible d’obtenir certaines dépendances via DependencyResolver.Current.GetService<T>(). Existe-t-il quelque chose de similaire dans ASP.NET Core?

8
analyser

Oui il y a. Dans ASP.NET Core 1.0.0, les services disponibles dans une demande de HttpContext sont exposés via la collection RequestServices.[1]:

this.HttpContext.RequestServices

Vous pouvez utiliser la méthode GetService pour extraire les dépendances en spécifiant le type de dépendance:

this.HttpContext.RequestServices.GetService(typeof(ISomeService));

En règle générale, vous ne devez pas utiliser ces propriétés directement, préférant demander les types dont vous avez besoin à vos classes via le constructeur de votre classe et laisser le framework injecter ces dépendances. Cela donne des classes qui sont plus faciles à tester et qui sont couplées plus librement.

[1] https://docs.asp.net/fr/latest/fundamentals/dependency-injection.html#request-services

9
Sergio Vicente

Si vous en avez vraiment besoin, vous pouvez en écrire un. Commencez par créer la classe AppDependencyResolver.

public class AppDependencyResolver
{
    private static AppDependencyResolver _resolver;

    public static AppDependencyResolver Current
    {
        get
        {
            if (_resolver == null)
                throw new Exception("AppDependencyResolver not initialized. You should initialize it in Startup class");
            return _resolver;
        }
    }

    public static void Init(IServiceProvider services)
    {
        _resolver = new AppDependencyResolver(services);
    }

    private readonly IServiceProvider _serviceProvider;

    public object GetService(Type serviceType)
    {
        return _serviceProvider.GetService(serviceType);
    }

    public T GetService<T>()
    {
        return _serviceProvider.GetService<T>();
    }

    private AppDependencyResolver(IServiceProvider serviceProvider)
    {
        _serviceProvider = serviceProvider;
    }
} 

Veuillez noter que _serviceProvider.GetService<T>(); n'est disponible que si vous ajoutez using Microsoft.Extensions.DependencyInjection;. Cet espace de noms sera disponible si vous ajoutez "Microsoft.Extensions.DependencyInjection": "1.0.0" à votre project.json. Vous devriez alors appeler la méthode Init dans votre classe startup. Par exemple

    public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory)
    {
        AppDependencyResolver.Init(app.ApplicationServices);
        //all other code

Après cela, vous pouvez l'utiliser n'importe où, comme en DependencyResolver.Current. Mais ma suggestion - ne l’utilisez que s’il n’ya plus d’autre choix.

8
YuriyP

Service disponible dans le noyau Asp.net, dans HttpContext

this.HttpContext.RequestServices

En utilisant ce service, il est possible d'obtenir un service. Vous pouvez également utiliser la méthode GetService pour récupérer les dépendances en spécifiant le type de dépendance:

this.HttpContext.RequestServices.GetService(typeof(ISomeService));
2
Jani Devang

Voici comment cela a fonctionné pour moi dans .Net Core 2.0

public ViewResult IndexWithServiceLocatorPattern([FromServices]ProductTotalizer totalizer)
{
    var repository = (IRepository)HttpContext.RequestServices.GetService(typeof(IRepository));
    ViewBag.HomeController = repository.ToString();
    ViewBag.Totalizer = totalizer.repository.ToString();
    return View("Index", repository.Products);
}

Si je devais le faire de manière classique, ce serait comme ci-dessous.

public class HomeController : Controller
{
    private readonly IRepository repo;

    /// <summary>
    /// MVC receives an incoming request to an action method on the Home controller. 
    /// MVC asks the ASP.NET service provider component for a new instance of the HomeController class.
    /// The service provider inspects the HomeController constructor and discovers that it has a dependency on the IRepository interface. 
    /// The service provider consults its mappings to find the implementation class it has been told to use for dependencies on the IRepository interface. 
    /// The service provider creates a new instance of the implementation class. 
    /// The service provider creates a new HomeController object, using the implementation object as a constructor argument.
    /// The service provider returns the newly created HomeController object to MVC, which uses it to handle the incoming HTTP request.
    /// </summary>
    /// <param name="repo"></param>
    public HomeController(IRepository repo)
    {
        this.repo = repo;
    }

    /// <summary>
    ///  Using Action Injection
    ///  MVC uses the service provider to get an instance of the ProductTotalizer class and provides it as an
    ///  argument when the Index action method is invoked.Using action injection is less common than standard
    ///  constructor injection, but it can be useful when you have a dependency on an object that is expensive to
    ///  create and that is required in only one of the action methods defined by a controller
    /// </summary>
    /// <param name="totalizer"></param>
    /// <returns></returns>
    public ViewResult Index([FromServices]ProductTotalizer totalizer)
    {
        ViewBag.Total = totalizer.repository.ToString();
        ViewBag.HomeCotroller = repo.ToString();
        return View(repo.Products);
    }
}
1
Bharat

Il existe des méthodes d'extension pour IServiceProvider: GetService, GetRequiredService et GetServices. Tous ont des versions génériques et non génériques. Dans le projet Web Asp.Net Core, vous pouvez obtenir une référence à IServiceProvider via DI ou auprès de IApplicationBuilder. Dans l'application Console, vous devez créer votre propre instance d'IServiceProvider et référence de magasin quelque part

var services = new ServiceCollection();
...
ServiceProvider = services.BuildServiceProvider();
1
Vitaly

Je pense que cela pourrait être un bon début:

C'est la documentation officielle pour l'injection de dépendance pour asp.net 5.

L'injection de dépendance est maintenant intégrée à asp.net 5, mais vous êtes libre d'utiliser d'autres bibliothèques telles que autofac. Celui par défaut fonctionne bien pour moi.

Dans votre classe de démarrage, vous avez une méthode comme celle-ci

public void ConfigureServices(IServiceCollection services)
{

    //IServiceCollection acts like a container and you 
    //can register your classes like this:

    services.AddTransient<IEmailSender, AuthMessageSender>();
    services.Singleton<ISmsSender, AuthMessageSender>();
    services.AddScoped<ICharacterRepository, CharacterRepository>();

}

De:

DependencyResolver Asp.net 5.0

0
Destrif