Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/334.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 简单注入器筛选器注入似乎正在重新初始化RegisterWebRequest注入项_C#_Ninject_Simple Injector_Actionfilterattribute - Fatal编程技术网

C# 简单注入器筛选器注入似乎正在重新初始化RegisterWebRequest注入项

C# 简单注入器筛选器注入似乎正在重新初始化RegisterWebRequest注入项,c#,ninject,simple-injector,actionfilterattribute,C#,Ninject,Simple Injector,Actionfilterattribute,我正在尝试从Ninject转移到简单的注入器,但在尝试复制与Ninject一起工作的功能时,我遇到了一个奇怪的问题 在Ninject,我提供了一项服务,其中包括: private readonly ICollection<Message> messages; 专用只读ICollection消息; 此服务已注册为 Bind<INotificationService>().To<NotificationService>() .InRequestScop

我正在尝试从Ninject转移到简单的注入器,但在尝试复制与Ninject一起工作的功能时,我遇到了一个奇怪的问题

在Ninject,我提供了一项服务,其中包括:

private readonly ICollection<Message> messages;
专用只读ICollection消息;
此服务已注册为

Bind<INotificationService>().To<NotificationService>()
    .InRequestScope();
Bind().To())
.InRequestScope();
此服务允许将消息(UI和错误)传回MVC站点

此服务已注入ActionFilterAttribute:

kernel.BindFilter<CriticalErrorAttribute>(FilterScope.Last, 1)
    .When((context, ad) => 
        !string.IsNullOrEmpty(ad.ActionName) &&
        ad.ControllerDescriptor.ControllerName.ToLower() != "navigation");
kernel.BindFilter(FilterScope.Last,1)
.当((上下文,广告)=>
!string.IsNullOrEmpty(ad.ActionName)&&
ad.ControllerDescriptor.ControllerName.ToLower()!=“导航”);
并在OnActionExecuted中使用

因为该服务是使用InRequestScope注册到Ninject的,所以推送到消息队列的任何项目都可以在Actionfiter中使用。这允许在必要时重定向到错误页面(显示关键错误)

我尝试用simpleinjector复制这一点:

container.RegisterPerWebRequest<INotificationService, NotificationService>();

container.RegisterInitializer<CriticalErrorAttribute>(handler =>
{
    handler.NotificationService =
        container.GetInstance<INotificationService>();
});
container.registerWebRequest();
container.RegisterInitializer(处理程序=>
{
handler.NotificationService=
container.GetInstance();
});
注入工作正常,但即使消息集合在进入ActionFilter之前包含消息,但一旦进入筛选器,消息集合将为空。这就像是忽略了RegisterWebRequest


如果您能帮助解决此问题,我们将不胜感激。

更新:

在Simple Injector 2.5中,MVC集成包中添加了一个新的
RegisterMVC IntegratedFilterProvider
扩展方法,该扩展方法取代了旧的
RegisterMVC AttributeFilterProvider
。这个新的
RegisterMVIntegratedFilterProvider
包含下面给出的
SimpleInjectorFilterAttributeFilterProvider
的行为,允许更好地将属性集成到简单注入器管道中。但是,这确实意味着默认情况下不会注入任何属性,但可以通过实现。建议使用新的
RegisterMvcIntegratedFilterProvider
而不是旧的
RegisterMvcAttributeFilterProvider
方法,该方法将在未来版本中标记为
[过时]


使用
RegisterMvcAttributeFilterProvider
扩展方法时,Simple Injector不会调用MVC属性上任何已注册的初始值设定项。如果在注入
NotificationService
的匿名委托内部设置断点,您将看到它从未被命中

但是,Simple Injector确实调用MVC属性上的
容器.InjectProperties
方法,但是
InjectProperties
执行隐式属性注入,这意味着它尝试注入类型上的所有公共属性,但如果无法注入属性(无论出于什么原因),它将跳过该方法

我打赌
CriticalErrorAttribute.NotificationService
属性的类型为
NotificationService
,而不是
INotificationService
。由于您没有显式注册
NotificationService
,因此容器将为您创建一个临时实例,这意味着您将获得与应用程序其余部分不同的
CriticalErrorAttribute
实例

快速修复:将属性类型更改为
INotificationService

老实说,我很遗憾曾经为Simple Injector实现了MVC集成包,以使用
InjectProperties
方法。隐式属性注入是非常有害的,因为它在出现错误配置时不会很快失败,我甚至考虑在将来取消对
InjectProperties
的支持。然而,问题是许多开发人员依赖于
InjectProperties
。可以直接调用它,也可以间接地让容器在MVC属性上注入属性

InjectProperties
不运行任何初始值设定项。这是出于设计考虑的,还有其他一些构造允许在容器未创建的对象上运行完整的初始化过程。然而,问题是,添加此选项可能会破坏现有客户端,因为这可能导致多次注入属性

在您的情况下,我建议一种不同的解决方案:

防止在应用程序的启动路径中调用container.RegisterMvcAttributeFilterProvider()。这将注册一个特殊的
FilterAttributeFilterProvider
,它在内部调用
InjectProperties
。您不想使用隐式属性注入,而是想要一个更显式(和完整)的行为。而是注册以下类:

内部密封类SimpleInjectorFilterAttributeFilterProvider
:过滤器属性过滤器提供程序
{
私有只读ConcurrentDictionary注册=
新的ConcurrentDictionary();
私有只读功能注册工厂;
公共SimpleInjectorFilterAttributeFilterProvider(容器)
:base(假)
{
this.registrationFactory=类型=>
生活方式.Transient.CreateRegistration(类型,容器);
}
公共覆盖IEnumerable GetFilters(
ControllerContext上下文,
ActionDescriptor(描述符)
{
var filters=base.GetFilters(上下文,描述符).ToArray();
foreach(过滤器中的var过滤器)
{
object instance=filter.instance;
var registration=registrations.GetOrAdd(
instance.GetType(),this.registrationFactory);
注册。初始化实例(实例);
}
回流过滤器;
}
}
您可以使用以下代码注册此自定义提供程序:

var filterProvider=
新SimpleInjec