【问题标题】:DryIOC WebAPI Fallback ControllerDryIOC WebAPI 后备控制器
【发布时间】:2016-03-23 13:27:21
【问题描述】:

我正在使用 DryIOC.WebAPI 来解析我的 APIControllers。

WebAPI 配置如下:

public static class WebApiConfig
{
    public static void Register(HttpConfiguration config)
    {
        // Web API configuration and services
        // Configure Web API to use only bearer token authentication.
        config.SuppressDefaultHostAuthentication();
        config.Filters.Add(new HostAuthenticationFilter(OAuthDefaults.AuthenticationType));


        config.EnableCors();
        config.MapHttpAttributeRoutes();

        config.Routes.MapHttpRoute(
            name: "DefaultApi",
            routeTemplate: "api/{controller}/{id}",
            defaults: new { id = RouteParameter.Optional }
        );

        Startup.IocContainer.WithWebApi(config);
        Startup.IocContainer.RegisterWebApiControllers(config);
    }
}

它工作得很好,直到我忘记在 IOC 容器中创建映射。在这种情况下,依赖解析器无法使用 DryIOC 创建 APIController 的实例。

当这种情况发生时,它会退回到默认的 WebAPI 解析器,然后会出现“无默认构造函数”错误。

这对我来说是不受欢迎的行为。如果 DryIOC 决议失败,我希望事情停在那里 - 没有回退到默认实现,也没有关于没有默认构造函数的不准确消息。我想知道 DryIOC 无法解决的类型,以便我修复它。

我怎样才能做到这一点?

【问题讨论】:

  • 您可以自己覆盖默认解析器,然后再将其传递给 DryIOC 并将其停在那里
  • 我在这里提出了 DryIOC 拉取请求:bitbucket.org/dadhi/dryioc/pull-requests/15/…
  • 在 DryIOC 框架中做出这样的改变是相当极端的。您应该利用 web api 允许的可扩展性。在查看 DryIOC 源如何替换默认解析器而不是包装它之后,我将编辑我的答案以展示如何包装 DryIOCResover 并抛出你想要的错误
  • @reach4thelasers 找到了一些文档 re: IDependencyResolver 这可能与您的要求相冲突。

标签: c# asp.net-web-api dryioc


【解决方案1】:

根据微软文档:

Dependency Injection in ASP.NET Web API 2

如果 GetService 方法无法解析类型,它应该返回 空值。如果 GetServices 方法无法解析类型,它应该 返回一个空的集合对象。

不要为未知类型抛出异常

这个接口的实现应该委托给底层 依赖注入容器提供注册的服务 请求的类型。当没有注册的服务时 请求的类型,ASP.NET MVC 框架期望实现 此接口从 GetService 返回 null 并返回一个空 从 GetServices 收集。

当 Web API 创建控制器实例时,它首先 调用IDependencyResolver.GetService,传入控制器类型。 您可以使用此可扩展性挂钩来创建控制器, 解决任何依赖关系。如果 GetService 返回 null,则 Web API 看起来 用于控制器类上的无参数构造函数。

您可以自己覆盖默认解析器

public static class ResolverHelper {
    public static void OverrideResolver(this HttpConfiguration httpConfiguration) {
        var innerResolver = httpConfiguration.DependencyResolver;
        var resolver = new MyDryIocDependencyResolver(innerResolver);
        httpConfiguration.DependencyResolver = resolver;
    }
}

并且在您的自定义解析器中失败了。

来自MyDryIocDependencyResolver的片段

public class MyDryIocDependencyResolver : IDependencyResolver { 
    IDependencyResolver innerResolver;

    public MyCustomDependencyResolver(IDependencyResolver innerResolver) {
        this.innerResolver = innerResolver;
    }

    public IDependencyScope BeginScope() {
        return this;
    }

    public object GetService(Type serviceType) {
        try {
            return innerResolver.Getservice(serviceType);
        } catch (Exception ex) {
            //TODO: Log resolution error
            return null;
        }
    }

    public IEnumerable<object> GetServices(Type serviceType) {
        try {
            return innerResolver.GetServices(serviceType);
        } catch (Exception ex) {
           //TODO: Log resolution error
           return new List<object>();
        }
    }

    public void Dispose() {
      // NO-OP 
    }
}

在您的注册中,您可以覆盖它

//...other code
Startup.IocContainer.WithWebApi(config);
Startup.IocContainer.RegisterWebApiControllers(config);
config.OverrideResolver();
//...other code

这样,如果/当 DryIocDependencyResolver 无法解析服务类型时,您仍然会知道未解析的内容,捕获它并返回建议指南中指示的默认值。两全其美。

希望有帮助

【讨论】:

  • 这确实是 MS 推荐的。但它的问题是,我们正在从集成的 IoC 库中丢失详细的异常。 DryIoc 和其他 IoC 提供了大量关于什么、为什么没有解决以及容器的状态的信息。因此,您可以更快地查明问题。
【解决方案2】:

使用所有可能信息检查控制器分辨率问题的另一种方法是使用IContainer.VerifyResolutions 方法。

例如:

var container = new Container().WithWebApi(config);
var errors = container.VerifyResolutions();
Debug.Assert(errors.Length == 0);

wiki 中的更多详细信息。

注意: 控制器的唯一问题是,当前的 DryIoc.WebApi 将控制器实现注册为具体的控制器类型及其所有实现的类型作为服务类型。因此对于一个未解决的class MyController: ApiController {} 方法VerifyResolutions 将返回3 个相同的错误:

  • 一个MyController
  • 一个ApiController
  • 和一个IHttpController

您可以将结果验证errorsFactory.FactoryID 分组,以获得更紧凑的输出。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-09-18
    • 2012-12-12
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多