Simple Injector 在调用 container.Verify() 时创建控制器实例

问题描述 投票:0回答:1

我在 Owin Selfhosted 中使用 Simple Injector,但我在调用

container.Verify()
时遇到问题。

当我调用

container.Verify()
时,它正在创建我所有控制器的一个实例,但在我的一些控制器中我有一些规则,并且根据配置它会抛出一个错误,说你不能使用路由。基于此,我只能在调用端点时创建控制器的实例。

这是我的启动代码:

public void Configuration(IAppBuilder app)
{
    var config = new HttpConfiguration();
    
    Monitor.VerifyConfingurations();
    ManipulateHttpConfiuration(config);
    app.UseWebApi(config);
    var container = ContainerGerenciador.NovoContainer();
    ConfigureDI(container, config);
    if (debug)
    {
        config.EnableSwagger(c => {
            
            c.SingleApiVersion("v1", "Swagger WSLinear API");
            c.IncludeXmlComments("WSLinearApi.XML");
            c.ResolveConflictingActions(apiDescriptions => apiDescriptions.First());
            c.UseFullTypeNameInSchemaIds();
        }).EnableSwaggerUi(x=> 
        {
            x.DisableValidator();
        });
    }
    var options = new FileServerOptions
    {                
        EnableDefaultFiles = false,
        DefaultFilesOptions = { DefaultFileNames = { "index.html" } },
        StaticFileOptions = { ContentTypeProvider = new CustomContentTypeProvider() }
    };
    app.UseFileServer(options);
}

private void ConfigureDI(Container container, HttpConfiguration config) 
{
    #region Register
    container.Register<ILinearLogger>(
    () => new Logger(new LinearLoggerConfiguration()
    {
        Path = PathFinder.GetLogsFilePath()
        
    }),Lifestyle.Transient);
    container.Register<IMyService,MyService>();
    Integrations.Setup.Register(container);
    #endregion
    container.RegisterWebApiControllers(config);
    config.DependencyResolver = new SimpleInjectorWebApiDependencyResolver(container);
    container.Verify();//here the error is thrown
}

控制器示例:

[RoutePrefix("api/SampleIntegration")]
[SwaggerResponse(HttpStatusCode.BadRequest, "Business Logic error", typeof(BusinessExceptionResponse))]
[SwaggerResponse(422, "Invalid Entity", typeof(CamposInvalidosExceptionResponse))]
public class SampleIntegrationController : ApiController
{
    private readonly IMyService _myService;
    public SampleIntegrationController(IMyService myservice) 
    {
     _myService = myservice;
     if(!_myService.IntegrationEnabled())
        throw new BusinessException("Sample Integration is not enabled! Enable it to access the route.")
        //above the error is thrown because simpleInjector creates an instance of this controller before the route is accessed
        //but I only this exception to throws only when the route is accessed (if the integration is not enabled)
    }

    [HttpGet]
    public HttpResponseMessage Get()
       => CreateResponse(() => _myService.GetData());


        //...
    }

我试图删除

container.Verify()
行,但是当调用第一个端点时它会抛出相同的错误(它创建所有其他控制器的实例)。

我该怎么做才能使 Simple Injector 在从实际路由调用之前不创建我的控制器实例?

c# asp.net owin simple-injector .net-4.8
1个回答
1
投票

随着版本 5 的推出,Simple Injector 会自动验证您的对象图,即使您没有显式调用

Verify
。此功能称为自动验证,可以关闭。您可以做的是将验证移至单元或集成测试,如 Simple Injector 文档中 here 所述。

虽然这是一个可能的解决方案,但我认为您应该为您的控制器考虑不同的验证策略。

正如您已经注意到的那样,在您的构造函数中包含此逻辑会导致困难,其中包括:

  • 允许 Simple Injector 验证您配置的对象图的困难,因为 Simple Injector 需要构建您的组件才能进行可靠的验证
  • 使用内部构造函数的依赖项会使对象构造缓慢且不可靠,而我们应该努力相反.

相反,请考虑以下替代方案:

  • 如果某些控制器的使用只允许在加载应用程序后加载(和修复)的某个配置上,请考虑过滤掉这些控制器并阻止它们被注册,而不是注册它们并阻止它们被调用。
  • 使用拦截机制,拦截对控制器的调用。例如,使用 Web API,您可以应用一个
    ActionFilter
    DelegatingHandler
    在每个调用的控制器操作之前关闭。这将验证逻辑保留在控制器之外,并允许在构造对象图后进行验证。
  • 在控制器调用其服务的地方拦截。例如,您可以为
    IMyService
    创建一个装饰器,以确保在调用
    IMyService
    时触发验证。如果控制器调用大量服务,此解决方案可能不太方便,因为您将为所有服务实现装饰器。另一方面,当您的控制器仅依赖于几个通用接口时,例如 command handlersquery handlers,您只需为每个通用接口实现一个控制器,这可能会使该解决方案更可行。
© www.soinside.com 2019 - 2024. All rights reserved.