- android - 多次调用 OnPrimaryClipChangedListener
- android - 无法更新 RecyclerView 中的 TextView 字段
- android.database.CursorIndexOutOfBoundsException : Index 0 requested, 光标大小为 0
- android - 使用 AppCompat 时,我们是否需要明确指定其 UI 组件(Spinner、EditText)颜色
我有一个 .NET MVC 5 .NET Framework 应用程序,我正在将其转换为 .NET Core 2.1
我有一个自定义操作过滤器,它在 .NET Framework 版本中被注册为 Filterconfig 类中的全局过滤器,如下所示:
public class FilterConfig
{
public static void RegisterGlobalFilters(GlobalFilterCollection filters)
{
filters.Add(new MyCustomActionFilter());
}
}
在 .NET 版本的自定义操作过滤器中,我使用的是服务定位器模式(我知道它可以被认为是一种反模式),如下所示:
var myService = DependencyResolver.Current.GetService<IMyService>();
我正在为 DI 使用 Simple Injector,在 .NET 版本中一切正常。在 .NET Core 版本中,我试图获得相同的功能,但 myService 始终为 null
我仍在使用 Simple Injector(因为解决方案中的所有其他项目都在使用它,并且它们没有转移到 .NET Core 项目(只有 Web 项目是)。
我的 Startup.cs 类有这段代码:
services.Configure<MvcOptions>(options =>
{
options.Filters.Add(new MyCustomActionFilter());
});
SimpleInjectorConfig.IntegrateSimpleInjector(services, container);
在我的服务层,我有一个从 Web 层调用的 SimpleInjector Registartion 类 - 然后它向下调用 DAL 层进行注册
public class SimpleInjectorRegistration
{
public static void RegisterServices(Container container)
{
container.Register<IMyService, MyService>();
//further code removed for brevity
当我使用自定义过滤器中的断点和此 RegisterServices 方法中的断点运行应用程序时,我可以看到首先命中 RegisterServices 方法中的断点,然后是自定义过滤器中的断点 - 这让我觉得一切都已连线正确放入容器中。
但是,我正在尝试使用 .NET Core 服务定位器模式在自定义过滤器中再次执行以下操作
var myService = filterContext.HttpContext.RequestServices.GetService<IMyService>();
但是结果总是空的?
我在这个设置中遗漏了什么吗?
------------ 更新--------------------
根据史蒂文斯的评论,我向我的操作过滤器添加了一个构造函数,并传入了 Simple Injector 容器。
现在我的 Startup 类是:
public class Startup
{
//Simple Injector container
private Container container = new Container();
public Startup(IConfiguration configuration)
{
Configuration = configuration;
}
public IConfiguration Configuration { get; }
public void ConfigureServices(IServiceCollection services)
{
JwtSecurityTokenHandler.DefaultInboundClaimTypeMap.Clear();
services.Configure<MvcOptions>(options =>
{
options.Filters.Add(new MyCustomActionFilter(container));
我的自定义过滤器现在如下所示,添加了构造函数:
public class MyCustomActionFilter : ActionFilterAttribute
{
private readonly IMyService _myService;
public MyCustomActionFilter(Container container)
{
_myService = container.GetService<IMyService>();
}
public override void OnActionExecuting(ActionExecutingContext filterContext)
{
//actual code of custom filter removed - use of MyService
我在 MyCustomActionFilter 的构造函数上设置了一个断点,我可以看到它被击中,但我抛出了一个错误:
SimpleInjector.ActivationException: 'The IDbContext is registered as 'Async Scoped' lifestyle, but the instance is requested outside the context of an active (Async Scoped) scope.'
MyService 对注入(inject)其中的 DbContext 有依赖性(它正在执行从数据库保存和检索数据的工作。
对于数据库上下文,我注册如下:
public class SimpleInjectorRegistration
{
public static void RegisterServices(Container container, string connectionString)
{
container.Register<IDbContext>(() => new MyDbContext(connectionString),
Lifestyle.Scoped);
}
}
最佳答案
在旧的 ASP.NET MVC 和新的 ASP.NET Core 中如何集成 Simple Injector 之间存在一些重大变化。在旧系统中,您可以替换 IDependencyResolver
。然而,ASP.NET Core 包含一个完全不同的模型,它有自己的内部 DI 容器。原样impossible要用 Simple Injector 替换内置容器,您将让两个容器并排运行。在这种情况下,内置容器将解析框架和第三方组件,而 Simple Injector 将为您组合应用程序组件。
当您调用 HttpContext.RequestServices.GetService
时,您将请求内置容器的服务,不是简单注入(inject)器。将 IMyService
注册添加到内置容器中,正如 TanvirArjel 的回答所暗示的那样,一开始似乎可行,但这完全从等式中跳过了 Simple Injector,这显然不是您希望的一种选择使用 Simple Injector 作为您的应用程序容器。
要模仿您之前的类似服务定位器的行为,您必须将 SimpleInjector.Container
注入(inject)到您的过滤器中,如下所示:
options.Filters.Add(new MyCustomActionFilter(container));
但是,如您在问题中所示,从构造函数中调用容器是错误的:
public class MyCustomActionFilter : ActionFilterAttribute
{
private readonly IMyService _myService;
public MyCustomActionFilter(Container container)
{
_myService = container.GetService<IMyService>(); // NEVER DO THIS!!!
}
...
}
WARNING: You should never resolve from the container from the constructor. Or in more general: you should never use any injected dependency from inside the constructor. The constructor should only store the dependency.
正如 Mark Seemann 所解释的那样,injection constructors should be simple .在这种情况下,情况甚至会变得更糟,因为:
MyCustomActionFilter
的构造函数期间,没有事件作用域,无法解析IMyService
IMyService
可以解析,MyCustomActionFilter
也是一个 Singleton
并且将 IMyService
存储在私有(private)字段中将导致隐藏 Captive Dependency .这可能会导致各种麻烦。您应该存储Container
依赖项,而不是存储已解析的IMyService
依赖项:
public class MyCustomActionFilter : ActionFilterAttribute
{
private readonly Container _container;
public MyCustomActionFilter(Container container)
{
_container = container;
}
public override void OnActionExecuting(ActionExecutingContext filterContext)
{
myService = container.GetService<IMyService>();
//actual code of custom filter removed - use of MyService
}
}
在调用 OnActionExecuting
期间,将有一个事件的简单注入(inject)器 Scope
,这将允许解析 IMyService
。最重要的是,由于 IMyService
未存储在私有(private)字段中,因此不会被缓存,也不会导致 Captive Dependency。
在您的问题中,您提到了 Service Locator anti-pattern .将 Container
注入(inject)过滤器是否实际上是服务定位器反模式的实现取决于过滤器所在的位置。正如马克·西曼 puts它:
A DI container encapsulated in a Composition Root is not a Service Locator - it's an infrastructure component.
换句话说,只要过滤器类位于内部您的Composition Root ,您没有应用服务定位器反模式。然而,这确实意味着您必须确保过滤器本身包含尽可能少的有趣行为。该行为应全部移至过滤器解析的服务。
关于c# - 带有返回 null 的简单注入(inject)器的 ASP.NET Core 2.1 服务定位器,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/53637611/
我已阅读有关依赖注入(inject)的信息。然后来了 构造函数注入(inject), setter/getter 注入(inject) 二传手注入(inject) 接口(interface)注入(in
我正在研究依赖注入(inject)模式。我看过很多例子,其中一个典型的例子是使用 XxxService/XxxRepository 作为例子。但是在我看来,按照UML的概念,类XxxRepositor
我开始使用 Google Guice。 我有一个简单的问题: javax.inject 的 @Inject 注释和 com.google.inject 的 有什么区别@Inject 一个 ? 谢谢。
当使用构造函数注入(inject)工厂方法时,依赖的属性不会得到解析。但是,如果在解析依赖的组件之前解析了工厂方法,则一切都会按预期工作。此外,当仅使用属性注入(inject)或构造函数注入(inje
我有这样的事情: class Root { public Root(IDependency dep) {} } class Dependency:IDependency { p
听完Clean Code Talks ,我开始明白我们应该使用工厂来组合对象。因此,例如,如果 House有一个 Door和 Door有一个 DoorKnob , 在 HouseFactory我们创建
情况:我需要在一些 FooClass 中进行惰性依赖实例化,所以我通过 Injector类作为构造函数参数。 private final Injector m_injector; public Foo
在编写代码时,我们应该能够识别两大类对象: 注入(inject)剂 新品 http://www.loosecouplings.com/2011/01/how-to-write-testable-cod
这个问题是关于 Unity Container 的,但我想它适用于任何依赖容器。 我有两个具有循环依赖关系的类: class FirstClass { [Dependency] pub
如果我有 10 个依赖项我需要注入(inject)并且不想在构造函数中有 10 个参数,我应该使用哪种注入(inject)模式? public class SomeClass { privat
我在使用 Angular2 DI 时遇到了问题。我尝试将一个类注入(inject)另一个类,它引发了以下错误: 留言:"Cannot resolve all parameters for 'Produ
对依赖注入(inject)还很陌生,我想弄清楚这是否是一种反模式。 假设我有 3 个程序集: Foo.Shared - this has all the interfaces Foo.Users -
我正在尝试了解 Angular 14 的变化,尤其是 inject()我可以将模块注入(inject)功能的功能,我不需要为此创建特殊服务..但我想我弄错了。 我正在尝试创建一些静态函数来使用包 ng
希望这个问题不是太愚蠢,我试图掌握更高级的编程原理,因此试图习惯使用 Ninject 进行依赖注入(inject)。 因此,我的模型分为几个不同的 .dll 项目。一个项目定义了模型规范(接口(int
我最近一直在大量使用依赖注入(inject)、测试驱动开发和单元测试,并且开始喜欢上它。 我在类中使用构造函数依赖,这样我就可以为单元测试注入(inject)模拟依赖。 但是,当您实际需要生产环境中的
我有下面的代码来使用 Guice 进行依赖注入(inject)。第一个是使用构造函数注入(inject),而另一个是直接在字段上方添加 @Inject。这两种方式有什么区别吗? Guice官网似乎推荐
这个问题在这里已经有了答案: Angular2 Beta dependency injection (3 个答案) 关闭 7 年前。 我正在使用 angular2 测试版。并在使用 @Inject
有没有可能做这样的事情? (因为我尝试过,但没有成功): @Injectable() class A { constructor(private http: Http){ // <-- Injec
我很恼火必须通过 Constructor 传递管道对象,因为我想为业务实体或要传递的值保留构造函数参数。 所以我想通过 setter ,但只要这些 setter 没有被填充,我的包含依赖项的对象就不应
假设我有这个: SomePage.razor: @inject Something something @page "/somepage" My Page @code { // Using
我是一名优秀的程序员,十分优秀!