像这样的事情让我头疼,这太疯狂了。但事实是:
对于非控制器类,如何使用net core的内置依赖项注入?请提供一个包含实例化的示例。
谢谢
我不确定这是最好的答案,但我决定这样做的方法是:
1)根据@BrunoLM在@SystemCrash建议的用ASP. NET Core DI解决实例这个问题上的回答,我创建了一个名为理解依赖注入的新项目,并粘贴在代码示例中。
重要提示:除非您访问上面的参考链接(#1),否则我接下来描述的内容将毫无意义。下面您看到的是一个基于另一个用户在另一个SO问题中提供的答案的部分解决方案。
2)接下来,我创建了另一个类,叫做其他服务。我添加了一个依赖于TestService的方法Do某物()。
3)在其他服务的构造函数中,我请求IServiceProvider以获得ITestService的具体实现,这样我就可以调用它的GenerateRandom()方法。
4)在HomeController.cs中,我只是将IServiceProvider引用传递给其他服务的构造函数。
这就是我所拥有的:
其他人ervice.cs
using System;
using Microsoft.Extensions.DependencyInjection;
namespace UnderstandingDependencyInjection.Services
{
public class OtherService
{
private readonly ITestService _testService;
public OtherService(IServiceProvider serviceProvider)
{
_testService = serviceProvider.GetService<ITestService>();
}
public int DoSomething()
{
var rnd = _testService.GenerateRandom();
return rnd * 2;
}
}
}
家庭控制器。反恐精英
using Microsoft.Extensions.DependencyInjection;
using UnderstandingDependencyInjection.Services;
namespace UnderstandingDependencyInjection.Controllers
{
public class HomeController : Controller
{
private readonly ITestService _testService;
private readonly IServiceProvider _serviceProvider;
public HomeController(IServiceProvider serviceProvider)
{
_serviceProvider = serviceProvider;
_testService = serviceProvider.GetService<ITestService>();
}
public IActionResult Index()
{
// This works!
// var rnd = _testService.GenerateRandom();
// What if I need to reference the TestService
// from another service? I.e., OtherService?
var otherService = new OtherService(_serviceProvider);
var rnd = otherService.DoSomething();
ViewBag.RandomNumber = rnd;
return View();
}
总之,这种技术的关键是传递控制器接收到的IServiceProvider的具体引用。。。从控制器传递到任何其他自定义类,这些自定义类也需要注册到ASP。NET核心的DI框架。
但是,我可能不想/不需要创建OtherService的实例。我可能只想静态调用一个方法,但该方法依赖于ASP管理的服务。NET核心MVC的依赖注入框架。现在怎么办?
在这种情况下,我所能理解的最好情况是,您需要将方法调用的引用传递给静态方法。看起来很恶心,我希望有更优雅的方式。。。但这是我发现的。
5) 在前面的步骤(如上)的基础上,我添加了一个名为StaticService的新类。
6)我创建了一个以IServiceProvider作为参数的方法。
7) 我使用IServiceProvider的具体实例来获取ITestService的具体实例。我用它来调用generateradom()。
8) 从控制器调用StaticService。DoSomething()方法将我一直持有的IServiceProvider的具体实例传递给它。
静态ervice.cs
using Microsoft.Extensions.DependencyInjection;
namespace UnderstandingDependencyInjection.Services
{
public class StaticService
{
// No constructors
public static int DoSomething(IServiceProvider serviceProvider)
{
var testService = serviceProvider.GetService<ITestService>();
var rnd = testService.GenerateRandom();
return rnd * 3;
}
}
}
家庭控制器。反恐精英
public IActionResult Index()
{
// This works!
// var rnd = _testService.GenerateRandom();
// What if I need to reference the TestService
// from another service? I.e., OtherService?
//var otherService = new OtherService(_serviceProvider);
//var rnd = otherService.DoSomething();
// What if I need to reference the TestService
// from another service with a STATIC method?
// Best I can tell, you have to pass the
// ServiceProvider in on the method call.
var rnd = StaticService.DoSomething(_serviceProvider);
ViewBag.RandomNumber = rnd;
return View();
}
简言之,是的。你最终在代码中到处传递服务提供者。有人会说,这让每个控制器和类都可以访问ASP中注册的每个服务。NET Core的DI。这是真的,看起来很糟糕。
但你的选择是什么?每个依赖于您的服务的类是否也应该被定义为服务并向DI注册?换句话说,我应该创建IOtherService,然后在其构造函数中传递一个具体的ITestService吗?
我可以做到这一点,但是现在我的控制器的构造函数需要ITestService和IOtherService。换句话说,为了正确工作,控制器需要知道OtherService如何完成其工作,以及它在内部使用ITestService。这似乎也很糟糕。
怎么办?
坦率地说,我认为最好的答案是:
在ASP中使用依赖项注入和工厂模式传递服务。网
@史蒂文在回答中说:
然而,这确实意味着您可能需要从ASP. NET Core的内置DI容器转移到功能更丰富的DI库,因为内置容器无法为ILogger进行上下文感知注册,同时库自动连接其他构造函数依赖关系也是如此。
您可以使用一个属性轻松定义静态类,如:
public static class StaticServiceProvider
{
public static IServiceProvider Provider { get; set; }
}
在定义了类之后,您必须在启动时确定服务的范围。配置服务方法:
public void ConfigureServices(IServiceCollection services)
{
//TODO: ...
services.AddScoped<IUnitOfWork, HttpUnitOfWork>();
services.AddSingleton<ISomeInterface, ISomeImplementation>();
}
然后在创业公司内部。配置方法启动时,您可以将提供程序设置为静态类属性:
public void Configure(IApplicationBuilder app, ...)
{
StaticServiceProvider.Provider = app.ApplicationServices;
//TODO: ...
}
现在,您可以轻松地调用StaticServiceProvider。供应商。GetService方法在应用程序中几乎无处不在:
var unitOfWork = (IUnitOfWork)StaticServiceProvider.Provider.GetService(typeof(IUnitOfWork));
只需为班级服务。
在初创阶段。反恐精英
services.AddScoped<AccountBusinessLayer>();
然后在控制器中,与其他服务相同:
private readonly AccountBusinessLayer _ABL;
在构造函数中包含,就像您为其他服务所做的那样:
public AccountController(
UserManager<ApplicationUser> userManager,
SignInManager<ApplicationUser> signInManager,IOptions<IdentityCookieOptions> identityCookieOptions,
IEmailSender emailSender,
ISmsSender smsSender,
ILoggerFactory loggerFactory,
RoleManager<IdentityRole> roleManager,
AccountBusinessLayer ABL
)
{
_userManager = userManager;
_signInManager = signInManager;
_externalCookieScheme = identityCookieOptions.Value.ExternalCookieAuthenticationScheme;
_emailSender = emailSender;
_smsSender = smsSender;
_logger = loggerFactory.CreateLogger<AccountController>();
_roleManager = roleManager;
_ABL = ABL;
}
有没有可能使控制器依赖于他们的服务,而不是通过使用服务容器,而是通过纯粹的构造函数依赖注入? 我希望以这种方式编写控制器: 不幸的是,正如我所看到的,Symfony ControllerResolver不通过ServiceContainer而是通过简单的调用创建新的控制器实例。
英文原文:http://emberjs.com/guides/controllers/dependencies-between-controllers/ 有时候,特别是在嵌套资源时,可能需要为两个控制器建立某种联系。以下面的路由为例: 1 2 3 4 5 App.Router.map(function() { this.resource("post", { path: "/posts/:po
问题内容: 我仍然是Angularjs的新手。我想在控制器中动态注入服务(我创建的)的依赖项。 但是,当我对具有依赖项的服务进行编码时,出现此错误: 错误:未知提供程序:$ windowProvider <-$ window <-base64 这是控制器的代码。 此代码有效: 此代码不起作用: 另一个问题是服务与控制器位于同一模块中。如果模块具有依赖项,则无法使用(我的模块配置中具有$ route
此时,我正在轻松地将东西注入控制器,在某些情况下构建自己的ResolversServices类。生活是美好的。 我不知道如何让框架自动注入到非控制器类中。工作原理是让框架自动注入我的控制器,这实际上是我项目的配置: 我在想我是否能为自己的课程做同样的事情。当我模仿控制器时,我假设我很接近,就像这样: 我想我失败的地方是当我这样叫它的时候: 我跟踪这个的问题实际上是所有关于DI的内容都是在控制器级别
2.1依赖注入和控制反转 Java应用程序-这是一个宽松的术语,它包括的范围从受限的嵌入式应用程序到n层的服务器端企业应用程序-通常组成程序的对象互相协作而构成正确的应用程序。因此,在一个应用程序中的对象彼此具有_依赖关系(dependencies)。_ 虽然Java平台提供了丰富的应用程序开发功能,但它缺乏将基本的模块组织成一个整体的方法,而将该任务留给了架构师和开发人员。虽然你可以使用如_工厂
2.1 依赖注入和控制反转 Java应用程序——范围从受限的、嵌入式的应用到N层的、服务器端的企业应用——通常由协作形成该程序的对象构成,因此一个应用程序中的对象彼此依赖。 虽然Java平台提供了大量的程序开发功能,但是它缺少将基础构建块组成一个整体的工具,而将此任务留给了架构师和开发者。尽管可以利用设计模式(比如Factory、Abstract Factory、Builder、Decorator