“已经为不同的Container实例注册了MVC筛选器提供程序。”在Simple Injector 2.6中 [英] "An MVC filter provider has already been registered for a different Container instance." in Simple Injector 2.6

查看:92
本文介绍了“已经为不同的Container实例注册了MVC筛选器提供程序。”在Simple Injector 2.6中的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我以前在属性之一中设置了属性注入设置,例如

I previously had the setup for property injection in one of my attributes as

 Container.RegisterInitializer<PermitAttribute>(initialize =>
 {
     initialize.QueryProcessor = Container.GetInstance<IQueryProcessor>();
 });

使用情况是

public class PermitAttribute : ActionFilterAttribute
{       
    public IQueryProcessor QueryProcessor { get; set; }
}

,但是在更新为simpleinjector 2.6.1之后,属性注入中断了。当我尝试访问PermitAttribute中的 QueryProcessor 对象时。它解析null值,因为Simple Injector配置仍然通过委托实例具有相同的属性注入。

but after updating to simpleinjector 2.6.1 The property injection broke. When I am trying to access QueryProcessor object inside PermitAttribute. It resolves null value where as the Simple Injector configuration still has the same property injection via delegate instance .

由于在v2.5中工作而在2.6.1中不再工作,因此财产注入行为是否发生重大变化?

Is there any breaking change in property injection behavior due to which it was working in v2.5 and its not working anymore in 2.6.1 ?

更新1:

配置中的行在MVC筛选器提供程序注册v2中的属性时引发错误.6.1

The Line in the configuration was throwing error for MVC filter provider registration for attributes in v2.6.1

 container.RegisterMvcIntegratedFilterProvider();

对此我发表了评论。它停止了财产注入工作。属性注入是我的属性之一。我想这是影响它的那条线。及其在v2.6.1中的抛出错误

For that I commented it . And it stopped the property injection working . The property injection was inside one of my attributes . I guess that's the line above which affects it. And its throwing error in v2.6.1

更新2:

消息


一个MVC筛选器提供程序已经为另一个
Container实例注册。此方法不支持为不同的
容器注册MVC筛选器提供程序。

An MVC filter provider has already been registered for a different Container instance. Registering MVC filter providers for different containers is not supported by this method.

StackTrace:

StackTrace :

at SimpleInjector.SimpleInjectorMvcExtensions.RequiresFilterProviderNotRegistered(Container container)
at SimpleInjector.SimpleInjectorMvcExtensions.RegisterMvcIntegratedFilterProvider(Container container)
at RemsPortal.App_Start.SimpleInjectorInitializer.Initialize() in d:\Projects Work\RemsPortal\V2.0 Web Portal\RemsPortal\App_Start\SimpleInjectorInitializer.cs:line 39

更新3:

整个配置

public static void Initialize()
{
    var container = new Container();

    InitializeContainer(container);
    container.RegisterMvcIntegratedFilterProvider();
    container.RegisterMvcControllers(Assembly.GetExecutingAssembly());

    container.Verify();

    DependencyResolver.SetResolver(new SimpleInjectorDependencyResolver(container));
}

private static void InitializeContainer(Container Container)
{
    Container.RegisterManyForOpenGeneric(typeof(IAsyncCommandHandler<,>),
        AppDomain.CurrentDomain.GetAssemblies());
    Container.RegisterOpenGeneric(typeof(ITransactionCommandHandler<,>),
        typeof(TransactionCommandHandlerDecorator<,>));
    Container.RegisterOpenGeneric(typeof(ICommandResult<>), 
        typeof(CommandHandlerResult<>));
    Container.Register<ICommandResolver, CommandResolver>();

    Container.Register<DbContext, RemsContext>();

    Container.RegisterOpenGeneric(typeof(IPager<>), typeof(PagerModel<>));

    //Container.RegisterPerWebRequest<DbContext, RemsContext>();

    Container.Register<UserManager<Users, Guid>, RemsUserManager>();
    Container.Register<RoleManager<Roles, Guid>, RemsRoleManager>();

    Container.Register<IUserStore<Users, Guid>, 
        UserStore<Users, Roles, Guid, UserLogins, UserRoles, Claims>>();
    Container.Register<IRoleStore<Roles, Guid>, RoleStore<Roles, Guid, UserRoles>>();

    Container.RegisterManyForOpenGeneric(typeof(IAsyncQueryHandler<,>),
        AppDomain.CurrentDomain.GetAssemblies());
    Container.RegisterManyForOpenGeneric(typeof(IAsyncQueryHandler<>),
        AppDomain.CurrentDomain.GetAssemblies());
    Container.RegisterManyForOpenGeneric(typeof(IQueryHandler<,>),
        AppDomain.CurrentDomain.GetAssemblies());
    Container.RegisterOpenGeneric(typeof(IQueryResult<>), typeof(QueryResult<>));

    Container.RegisterOpenGeneric(typeof(IPaginator<>), typeof(Paginator<>));
    Container.Register<IPaginator, Paginator>();

    Container.RegisterOpenGeneric(typeof(IAsyncQueryHandler<>), typeof(BaseQuery<>));
    Container.RegisterOpenGeneric(typeof(IQueryHandler<>), typeof(BaseQuery<>));

    Container.Register<IQueryProcessor, QueryProcessor>(Lifestyle.Singleton);

    Container.Register<ILog, NLogger>(Lifestyle.Singleton);

    Container.RegisterInitializer<PermitAttribute>(initialize =>
    {
        initialize.QueryProcessor = Container.GetInstance<IQueryProcessor>();
    });

    Container.RegisterInitializer<BaseController>(initialize =>
    {
        initialize.QueryProcessor = Container.GetInstance<IQueryProcessor>();
        initialize.Logger = Container.GetInstance<ILog>();
    });

    Container.RegisterInitializer<BaseCommandHandler>(initialize =>
    {
        initialize.UserManager = Container.GetInstance<RemsUserManager>();
        initialize.RoleManager = Container.GetInstance<RemsRoleManager>();
        initialize.RemsContext = Container.GetInstance<RemsContext>();
        initialize.QueryProcessor = Container.GetInstance<IQueryProcessor>();
    });

    Container.RegisterInitializer<BaseHandler>(initialize =>
    {
        initialize.UserManager = Container.GetInstance<RemsUserManager>();
        initialize.RolesManager = Container.GetInstance<RemsRoleManager>();
    });
}


推荐答案

您看到的异常是由版本2.6中已添加的验证检查引起的,该检查阻止您多次调用 RegisterMvcAttributeFilterProvider RegisterMvcIntegratedFilterProvider 针对不同的容器实例。在此处中对此问题进行了详细说明。

The exception you are seeing is caused by a verification check that has been added to version 2.6 that prevents you from calling RegisterMvcAttributeFilterProvider and RegisterMvcIntegratedFilterProvider multiple times for different container instances. The problem is described in more details here.

解决方案是确保在整个应用程序域的持续时间内以及自 RegisterMvcIntegratedFilterProvider simpleinjector.readthedocs.org/en/latest/registermvcattributefilterprovider-is-deprecated.html rel = nofollow noreferrer> RegisterMvcAttributeFilterProvider 已弃用,防止进行任何调用完全不使用该传统方法。因此,如果您仅在其中调用一次,请在此行上设置一个断点,因为您可能会两次调用 Initialize()方法!

The solution is to make sure RegisterMvcIntegratedFilterProvider is called only once in your code for the duration of the complete app domain and since RegisterMvcAttributeFilterProvider is deprecated, prevent having any calls at all to that legacy method. So if you only have one call in there, set a break point on this line, because you might be calling the Initialize() method twice!

新的 RegisterMvcIntegratedFilterProvider 允许在简单的注入器管道,可确保在属性上调用 RegisterInitializer 方法。

The new RegisterMvcIntegratedFilterProvider allows complete integration of MVC attributes in the Simple Injector pipeline which makes sure that the RegisterInitializer method is called on attributes.

不过,另一种选择是启用显式属性注入来获取属性,或者使用被动属性,如此处

Another option though is to enable explicit property injection for attributes, or to fall back on the use of passive attributes as shown here.

但是关于财产注入的一项说明。我注意到您广泛使用(显式)属性注入,尤其是对于您的基类。但是,从设计的角度来看,最好一起删除所有基类,因为它们至少是一种设计上的味道,但以后可能会成为维护问题。他们可能违反单一职责原则,或者至少掩盖了派生类型具有太多依赖关系,这通常意味着太多责任。我自己使用MVC和命令处理程序和查询处理程序,我始终能够防止使用基类。如果具体处理程序需要依赖项,则应将其简单地注入该类型的构造函数中。

But one note on property injection. I noticed you make extensive use of (explicit) property injection, especially for your base classes. From a design perspective however, it's better to remove the base classes all together, because they are a design smell at least, but might become maintenance problems later on. They might violate the Single Responsibility Principle or at least hide that derived types have too many dependencies, which often means too many responsibilities. I create quite big applications myself with MVC and command handlers and query handlers and I am always able to prevent the use of base classes. If a concrete handler needs a dependency, you should simply inject it into the constructor of that type. Prevent hiding that dependency by (ab)using a base type.

在使用 RegisterMvcIntegratedFilterProvider时,应注意一个重要的细节。 。 MVC缓存过滤器属性(上帝知道原因),这意味着该属性基本上已成为单例。这意味着此过滤器属性具有的每个依赖关系也将变为单例。如果这样的依赖关系本身没有注册为单例,这当然是一个大问题。它变成了圈养依赖性。尽管Simple Injector包含诊断警告来检测此类错误,但Simple Injector将无法使用属性检测到此情况,因为属性未在容器中注册。因此,我的建议是完全不要在属性中使用属性注入。 我们正在考虑从MVC集成库中弃用 RegisterMvcIntegratedFilterProvider 方法。

There is one important detail that you should be aware about when you use the RegisterMvcIntegratedFilterProvider. MVC caches filter attributes (god knows why) and this means that such attribute is basically becoming a singleton. This implies that every dependency this filter attribute has, becomes a singleton as well. This is of course be big problem if such dependency is not registered as singleton itself; it becomes a captive dependency. Although Simple Injector contains a diagnostic warning to detect these kinds of errors, Simple Injector will be unable to detect this with attributes, because attributes are not registered in the container. Because of this, my advice is to stay away from using property injection in your attributes at all. We are considering to deprecate the RegisterMvcIntegratedFilterProvider method from the MVC integration library.

这篇关于“已经为不同的Container实例注册了MVC筛选器提供程序。”在Simple Injector 2.6中的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆