ASP.NET Core DependencyResolver

时间:2016-06-14 13:38:33

标签: c# dependency-injection asp.net-core-mvc

在ASP.NET MVC中,可以通过DependencyResolver.Current.GetService<T>()获得一些依赖关系。 ASP.NET Core中有类似的东西吗?

7 个答案:

答案 0 :(得分:11)

是的,有。在ASP.NET Core 1.0.0中,来自HttpContext的请求中可用的服务通过RequestServices集合 [1] 公开:

this.HttpContext.RequestServices

您可以使用GetService方法通过指定依赖项的类型来检索依赖项:

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

通常,您不应该直接使用这些属性,而是更喜欢通过类的构造函数请求类所需的类,并让框架注入这些依赖项。这会产生更容易测试的类,并且更松散地耦合。

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

答案 1 :(得分:8)

如果你真的需要它,你可以自己写一个。首先 - 创建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;
    }
} 

请注意_serviceProvider.GetService<T>();仅在您添加using Microsoft.Extensions.DependencyInjection;时才可用。如果您向"Microsoft.Extensions.DependencyInjection": "1.0.0"添加project.json,则可以使用该命名空间。 您应该在Init课程中调用startup方法。例如

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

之后,您可以在任何地方使用它,与DependencyResolver.Current相同。但我的建议 - 只有在没有其他选择的情况下才使用它。

答案 2 :(得分:2)

Asp.net核心提供的服务,在HttpContext

之内
this.HttpContext.RequestServices

通过使用此服务,可以获得服务。您还可以使用GetService方法通过指定依赖项的类型来检索依赖项:

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

答案 3 :(得分:1)

IServiceProvider有扩展方法:GetService,GetRequiredService和GetServices。所有都有通用和非通用版本。 在Asp.Net Core Web项目中,您可以通过DI或IApplicationBuilder获取对IServiceProvider的引用。 在Console应用程序中,您应该创建自己的IServiceProvider实例并在某处存储引用

wp_list_categories(array('title_li' => false, 'style' => false));

答案 4 :(得分:1)

以下是.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);
}

如果我必须用经典的方式来做,那就像下面一样。

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);
    }
}

答案 5 :(得分:0)

我认为这可能是一个好的开始:

这是asp.net 5依赖注入的官方文档。

依赖注入现在内置于asp.net 5中,但您可以自由使用其他库,如autofac。默认的一个对我来说很好。

在你的starup课程中,你有一个像这样的方法

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>();

}

自:

DependencyResolver Asp.net 5.0

答案 6 :(得分:0)

我也想添加到主要答案中, 在razor视图页面中,我们可以对DI使用@inject指令。它将检索目标服务以在Asp.Net core上查看页面,像这样

@inject XYZ.Web.Services.CurrencyService currencyService;