1

我正在使用 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 无法解决的类型,所以我可以修复它。

我怎样才能做到这一点?

4

2 回答 2

1

使用所有可能信息检查控制器分辨率问题的另一种方法是使用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获得更紧凑的输出。

于 2016-03-24T16:33:12.363 回答
1

根据微软文档:

ASP.NET Web API 2 中的依赖注入

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

不要为未知类型抛出异常

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

当 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 无法解析服务类型时,您仍然会知道未解析的内容,捕获它并返回建议指南中指示的默认值。两全其美。

希望有帮助

于 2016-03-23T14:35:35.340 回答