Web Api使用IDependencyResolver实现启动异常

Pre*_*ngh 27 dependency-injection unity-container asp.net-web-api dependency-resolver

我正在开发Web Api,我决定使用自定义DependencyResolver.我引用了[Web API控制器的依赖注入]一文.到目前为止,依赖注入控制器的所有方面都运行良好.我的Owin启动类的配置代码片段

private void RegisterIoC(HttpConfiguration config)
{
    _unityContainer = new UnityContainer();
    _unityContainer.RegisterType<IAccountService, AccountService>();
    .........
    .........
    config.DependencyResolver = new UnityResolver(_unityContainer);
}
Run Code Online (Sandbox Code Playgroud)

但是当Api第一次启动时,在UnityResolver的 GetService方法中抛出(但被捕获)一些ResolutionFailedException .这是异常消息

"Exception occurred while: while resolving. 
Exception is: InvalidOperationException - 
The current type, System.Web.Http.Hosting.IHostBufferPolicySelector, 
**is an interface and cannot be constructed. Are you missing a type mapping?**"
Run Code Online (Sandbox Code Playgroud)

上述同样的异常抛出以下几种类型

System.Web.Http.Hosting.IHostBufferPolicySelector
System.Web.Http.Tracing.ITraceWriter
System.Web.Http.Metadata.ModelMetadataProvider
System.Web.Http.Tracing.ITraceManager
System.Web.Http.Dispatcher.IHttpControllerSelector
System.Web.Http.Dispatcher.IAssembliesResolver
System.Web.Http.Dispatcher.IHttpControllerTypeResolver
System.Web.Http.Controllers.IHttpActionSelector
System.Web.Http.Controllers.IActionValueBinder
System.Web.Http.Validation.IBodyModelValidator
System.Net.Http.Formatting.IContentNegotiator
Run Code Online (Sandbox Code Playgroud)

我知道抛出这些ResolutionFailedException是因为我没有在上面的类型的单位配置中提供映射.

现在这里是我的问题: -,如果我实现自定义统一DependencyResolver我需要定义上述类型的映射,如果需要定义它们对应的默认实现类型,或者是否有一些替代方法来实现DependencyResolver.我真的担心即使应用程序运行正常,但未能解决上述类型可能会导致严重问题.请帮忙.

最后一个添加: - 对于以下类型,当我向web api请求任何操作时抛出相同的ResolutionFailedException

System.Web.Http.Dispatcher.IHttpControllerActivator
System.Web.Http.Validation.IModelValidatorCache
System.Web.Http.Controllers.IHttpActionInvoker
Run Code Online (Sandbox Code Playgroud)

小智 21

我使用Unity与WebApi和OWIN/Katana运行同样的问题.

我的解决方案是使用Unity.WebApi Nuget包中定义的UnityDependencyResolver而不是我自己的自定义实现(如上面的@Omar Alani)

Install-Package Unity.WebAPI
Run Code Online (Sandbox Code Playgroud)

请注意,程序包将尝试在App_Start中添加名为UnityConfig.cs的文件(我自己使用的文件名).

在UnityConfig.cs文件中,包将添加代码来注册容器,GlobalConfiguration.Configuration.DependencyResolver而不是我们想要的OWIN.

所以不要使用:

GlobalConfiguration.Configuration.DependencyResolver = new UnityDependencyResolver(container);
Run Code Online (Sandbox Code Playgroud)

改用:

config.DependencyResolver = new UnityDependencyResolver(container);
Run Code Online (Sandbox Code Playgroud)

为了完整性:

我的UnityConfig.cs

public static class UnityConfig
{
    public static void Register(HttpConfiguration config)
    {
        var container = new UnityContainer();

        // Your mappings here

        config.DependencyResolver = new UnityDependencyResolver(container);
    }
}
Run Code Online (Sandbox Code Playgroud)

我的Startup.cs

[assembly: OwinStartup(typeof(UnityTest.BusinessLayer.Api.ApiStartup))]
namespace UnityTest.BusinessLayer.Api
{
    public partial class ApiStartup
    {
        public void Configuration(IAppBuilder app)
        {

            app.UseCors(Microsoft.Owin.Cors.CorsOptions.AllowAll);

            HttpConfiguration httpConfig = new HttpConfiguration();

            UnityConfig.Register(httpConfig);

            ConfigureAuth(app); //In App_Start ->Startup.Auth

            WebApiConfig.Register(httpConfig);

            app.UseWebApi(httpConfig);
    }
  }
}
Run Code Online (Sandbox Code Playgroud)

  • 通过这篇文章节省了我很多时间,你是一个传奇!几乎你的句子"使用Unity.WebApi Nuget包中定义的UnityDependencyResolver而不是我自己的自定义实现"就是我所需要的.再次感谢! (3认同)

Ben*_*hes 6

如果上述任何一种解决方案仍然无法为人们所用,我就是这样解决的.

花了一天时间追逐这个错误,结果证明是某种VS缓存问题.出于绝望,我删除了所有.suo文件和force-get-latest,这似乎解决了这个问题.


Duo*_*ran 5

的实现Unity.WebAPI与问题中提到的实现没有太大不同。我喜欢OP引用的版本,因为它只忽略ResultionFailedException并让其余部分在堆栈中传播。Unity.WebAPI抑制所有异常。我要做的就是忽略我们知道可以安全执行的错误并记录(或重新抛出)其他错误。

public object GetService(Type serviceType)
{
    try
    {
        return container.Resolve(serviceType);
    }
    catch(ResolutionFailedException ex)
    {
        if (!(typeof(System.Web.Http.Tracing.ITraceWriter).IsAssignableFrom(serviceType))
           || typeof(System.Web.Http.Metadata.ModelMetadataProvider).IsAssignableFrom(serviceType)
           //...
        ))
        {
            // log error
        }
    }

    return null;
}
Run Code Online (Sandbox Code Playgroud)


Mun*_*ini 5

这是很久以前问过的,但是我遇到了这里未提及的解决方案,因此也许有人仍然对此感兴趣。

就我而言,这些异常已由Unity(或其他任何东西)在内部捕获,但是我在Visual Studio中的异常设置使它们仍然显示出来。我只需要取消选中“显示此异常类型时中断”复选框,应用程序就可以正常运行。


Oma*_*ani 4

通常,您不需要使用 Unity。我统一使用 IDependencyResolver 的此实现,并且无需注册或映射除接口/服务之外的其他内容。

public class UnityDependencyInjectionResolver : Disposable, IDependencyResolver
{
    protected IUnityContainer Container;

    public UnityDependencyInjectionResolver(IUnityContainer container)
    {
        if (container == null)
        {
            throw new ArgumentNullException("container");
        }

        Container = container;
    }

    public object GetService(Type serviceType)
    {
        try
        {
            return Container.Resolve(serviceType);
        }
        catch (ResolutionFailedException)
        {
            return null;
        }
    }

    public T GetService<T>()
    {
        try
        {
            var serviceType = typeof(T);
            return (T)Container.Resolve(serviceType);
        }
        catch (ResolutionFailedException)
        {
            return default(T);
        }
    }

    public T GetService<T>(string name)
    {
        try
        {
            var serviceType = typeof (T);
            return (T) Container.Resolve(serviceType, name);
        }
        catch (ResolutionFailedException)
        {
            return default(T);
        }
    }

    public IEnumerable<object> GetServices(Type serviceType)
    {
        try
        {
            return Container.ResolveAll(serviceType);
        }
        catch (ResolutionFailedException)
        {
            return new List<object>();
        }
    }

    public IDependencyScope BeginScope()
    {
        var child = Container.CreateChildContainer();
        return new UnityDependencyInjectionResolver(child);
    }

    protected override void DisposeManagedResources()
    {
        if (Container == null)
        {
            return;
        }

        Container.Dispose();
        Container = null;
    }
}
Run Code Online (Sandbox Code Playgroud)

其中 Disposable 只是实现 IDispoable 的基类。

希望有帮助。

  • 我使用相同的 UnityResolver,但上面提到的第一次机会异常仍然发生,特别是在第 26 行 return Container.Resolve(serviceType) 处。Unity 是否无法检查实现是否已注册,如果没有则回退,而不是依赖异常。我也有点担心依赖例外行为。 (3认同)