"MVC过滤器提供程序已经注册了另一个Container实例." 在Simple Injector 2.6中

Joy*_*Joy 4 asp.net-mvc dependency-injection simple-injector

我以前在我的一个属性中设置了属性注入设置

 Container.RegisterInitializer<PermitAttribute>(initialize =>
 {
     initialize.QueryProcessor = Container.GetInstance<IQueryProcessor>();
 });
Run Code Online (Sandbox Code Playgroud)

用法是

public class PermitAttribute : ActionFilterAttribute
{       
    public IQueryProcessor QueryProcessor { get; set; }
}
Run Code Online (Sandbox Code Playgroud)

但在更新到simpleinjector之后2.6.1属性注入破了.当我试图访问QueryProcessorPermitAttribute内的对象时.它解析了null值,因为Simple Injector配置仍然通过委托实例注入相同的属性.

由于它在v2.5中工作并且在2.6.1中不再起作用,属性注入行为是否有任何重大变化?

更新1:

配置中的Line为MVC过滤器提供程序注册v2.6.1中的属性引发了错误

 container.RegisterMvcIntegratedFilterProvider();
Run Code Online (Sandbox Code Playgroud)

为此我评论了它.它阻止了房产注入工作.属性注入是我的一个属性.我猜这就是影响它的线.它在v2.6.1中抛出错误

更新2:

信息

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

堆栈跟踪 :

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
Run Code Online (Sandbox Code Playgroud)

更新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>();
    });
}
Run Code Online (Sandbox Code Playgroud)

Ste*_*ven 7

您所看到的异常是由已添加到2.6版本会阻止您调用验证检查引起的RegisterMvcAttributeFilterProvider,并RegisterMvcIntegratedFilterProvider多次为不同的容器实例.这里将更详细地描述该问题.

解决方案是确保RegisterMvcIntegratedFilterProvider在整个应用程序域的持续时间内仅在代码中调用一次,并且因为RegisterMvcAttributeFilterProvider不推荐使用,所以不要对该传统方法进行任何调用.因此,如果您只有一个呼叫,请在此行设置一个断点,因为您可能会调用该Initialize()方法两次!

new RegisterMvcIntegratedFilterProvider允许在Simple Injector管道中完全集成MVC属性,从而确保RegisterInitializer在属性上调用该方法.

另一种选择,虽然是使明确的财产注入的属性,或依傍使用的被动属性,如图所示这里.

但关于房地产注资的一点说明.我注意到你大量使用(显式)属性注入,特别是对你的基类.但是从设计的角度来看,最好一起删除基类,因为它们至少是一种设计气味,但可能会在以后成为维护问题.它们可能违反单一责任原则或至少隐藏派生类型具有太多依赖性,这通常意味着太多的责任.我自己使用MVC和命令处理程序以及查询处理程序创建了非常大的应用程序,我始终能够阻止使用基类.如果具体的处理程序需要依赖项,则只需将其注入该类型的构造函数中即可.防止使用基类型(ab)隐藏该依赖项.

使用时,您应该注意一个重要的细节RegisterMvcIntegratedFilterProvider.MVC缓存过滤器属性(上帝知道为什么),这意味着这样的属性基本上变成了单身.这意味着此过滤器属性所具有的每个依赖项也会成为单例.如果这种依赖没有被注册为单身本身,这当然是个大问题; 它成为一种俘虏的依赖.尽管Simple Injector包含诊断警告以检测这些类型的错误,但Simple Injector将无法使用属性检测到此错误,因为属性未在容器中注册.因此,我的建议是远离在属性中使用属性注入.我们正在考虑RegisterMvcIntegratedFilterProvider从MVC集成库中弃用该方法.