Dependency injection IDependencyResolver实现的Web Api启动异常

Dependency injection IDependencyResolver实现的Web Api启动异常,dependency-injection,unity-container,asp.net-web-api,dependency-resolver,Dependency Injection,Unity Container,Asp.net Web Api,Dependency Resolver,我正在开发一个Web Api,我决定使用自定义DependencyResolver。我指的是这篇文章。到目前为止,在向控制器注入依赖项方面,一切都运行良好。Owin启动类中的配置代码片段 private void RegisterIoC(HttpConfiguration config) { _unityContainer = new UnityContainer(); _unityContainer.RegisterType<IAccountService, Accoun

我正在开发一个Web Api,我决定使用自定义DependencyResolver。我指的是这篇文章。到目前为止,在向控制器注入依赖项方面,一切都运行良好。Owin启动类中的配置代码片段

private void RegisterIoC(HttpConfiguration config)
{
    _unityContainer = new UnityContainer();
    _unityContainer.RegisterType<IAccountService, AccountService>();
    .........
    .........
    config.DependencyResolver = new UnityResolver(_unityContainer);
}
上述相同的引发以下类型的异常

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
我知道抛出这些ResolutionFailedException是因为我在unity配置中没有为上述类型提供映射

现在我的问题是:-,如果我实现自定义unity DependencyResolver,我需要定义上述类型的映射,如果需要定义它们对应的默认实现类型,或者是否有其他方法实现DependencyResolver。我真的很担心,即使应用程序现在运行良好,未能解决上述类型可能会导致严重的问题以后请帮助

最后添加一项:- 对于以下类型,当我向my web api请求任何操作时,会引发相同的ResolutionFailedException

System.Web.Http.Dispatcher.IHttpControllerActivator
System.Web.Http.Validation.IModelValidatorCache
System.Web.Http.Controllers.IHttpActionInvoker

通常情况下,你不需要团结一致。 我将此实现用于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;
    }
}
公共类UnityDependencyInjectionResolver:一次性的IDependencyResolver
{
受保护的IUnity容器;
公共UnityDependencyInjectionResolver(IUnityContainer容器)
{
if(容器==null)
{
抛出新的ArgumentNullException(“容器”);
}
容器=容器;
}
公共对象GetService(类型serviceType)
{
尝试
{
返回容器解析(serviceType);
}
捕获(解决失败异常)
{
返回null;
}
}
公共服务
{
尝试
{
var serviceType=typeof(T);
返回(T)容器解析(serviceType);
}
捕获(解决失败异常)
{
返回默认值(T);
}
}
公共GetT服务(字符串名称)
{
尝试
{
var serviceType=typeof(T);
return(T)Container.Resolve(serviceType,name);
}
捕获(解决失败异常)
{
返回默认值(T);
}
}
公共IEnumerable GetServices(类型serviceType)
{
尝试
{
返回容器.ResolveAll(serviceType);
}
捕获(解决失败异常)
{
返回新列表();
}
}
公共IDependencyScope BeginScope()
{
var child=Container.CreateChildContainer();
返回新的UnitedPendencyInjectionResolver(子级);
}
受保护的覆盖void DisposeManagedResources()
{
if(容器==null)
{
返回;
}
Container.Dispose();
Container=null;
}
}
其中Disposable只是实现IDisTable的基类


希望能有所帮助。

我使用Unity与WebApi和OWIN/Katana遇到了同样的问题

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

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

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

因此,与其使用:

GlobalConfiguration.Configuration.DependencyResolver = new UnityDependencyResolver(container);
更改为使用:

config.DependencyResolver = new UnityDependencyResolver(container);
完整性:

我的UnityConfig.cs

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

        // Your mappings here

        config.DependencyResolver = new UnityDependencyResolver(container);
    }
}
我的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);
    }
  }
}

Unity.WebAPI
的实现与问题中提到的没有太大区别。我喜欢OP提到的版本,因为它只忽略
resultationfailedexception
,并让其余部分向上传播
Unity.WebAPI
抑制所有异常。我要做的是忽略我们知道安全的错误,并记录(或重发)其他错误


我已删除dependencyResolver,此问题已解决

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

        // Your mappings here

        config.DependencyResolver = null;
    }
}

如果上述任何一种解决方案仍然不适用于人们,下面是我如何解决的


在花了一天的时间追查这个错误之后,结果发现这是某种VS缓存问题。出于绝望,我删除了所有.suo文件并强制获取最新版本,这似乎解决了问题。

这是很久以前提出的问题,但我遇到了一个此处未提及的解决方案,因此可能仍有人感兴趣


在我的例子中,这些异常已经被Unity(或其他什么)在内部捕获,但我在VisualStudio中的异常设置使它们仍然显示出来。我只需取消选中“显示此异常类型时中断”复选框,应用程序就可以正常运行。

由于这似乎仍有争议,下面是我的代码版本

/// <summary>
/// Specifies the Unity configuration for the main container.
/// </summary>
public class UnityConfig
{
    private static Lazy<IUnityContainer> container = new Lazy<IUnityContainer>(() =>
    {
        var container = new UnityContainer();

        RegisterTypes(container);

        return container;
    });

    /// <summary>
    /// Gets the configured Unity container.
    /// </summary>
    public static IUnityContainer GetConfiguredContainer()
    {
        return container.Value;
    }

    public static void RegisterTypes(IUnityContainer container)
    {
        // Keeping this separate allows easier unit testing
        // Your type mappings here
    }
}
最后,bits是在Owin中间件中使用作用域容器以及直接WebAPI的扩展

public static class AppBuilderExtensions
{
    public static IAppBuilder UseDependencyResolverScope(this IAppBuilder app, IDependencyResolver resolver)
    {
        return app.Use<DependencyResolverScopeMiddleware>(resolver);
    }
}

/// <summary>
/// Wraps middleware in a <see cref="IDependencyResolver"/> scope.
/// </summary>
public class DependencyResolverScopeMiddleware : OwinMiddleware
{
    private readonly IDependencyResolver resolver;

    public DependencyResolverScopeMiddleware(OwinMiddleware next, IDependencyResolver resolver) : base(next)
    {
        this.resolver = resolver;
    }

    public override async Task Invoke(IOwinContext context)
    {
        using (var scope = resolver.BeginScope())
        {
            context.SetDependencyScope(scope);
            await Next.Invoke(context);
        }
    }
}
公共静态类AppBuilderExtensions
{
公共静态IAppBuilder UseDependencyResolverScope(此IAppBuilder应用程序,IDependencyResolver解析器)
{
返回应用程序使用(解析器);
}
}
/// 
///将中间件包装到范围中。
/// 
公共类依赖解析镜中间件:OwinMiddleware
{
专用只读IDependencyResolver解析器;
公共依赖解析镜中间件(OwinMiddleware next,IDependencyResolver resolver):基础(next)
{
this.resolver=解析器;
}
公共重写异步任务调用(IOwinContext上下文)
{
使用(var scope=resolver.BeginScope())
{
context.SetDependencyScope(范围);
等待下一步。调用(上下文);
}
}
}
理由
public static class UnityConfig
{
    public static void Register(HttpConfiguration config)
    {
        var container = new UnityContainer();

        // Your mappings here

        config.DependencyResolver = null;
    }
}
/// <summary>
/// Specifies the Unity configuration for the main container.
/// </summary>
public class UnityConfig
{
    private static Lazy<IUnityContainer> container = new Lazy<IUnityContainer>(() =>
    {
        var container = new UnityContainer();

        RegisterTypes(container);

        return container;
    });

    /// <summary>
    /// Gets the configured Unity container.
    /// </summary>
    public static IUnityContainer GetConfiguredContainer()
    {
        return container.Value;
    }

    public static void RegisterTypes(IUnityContainer container)
    {
        // Keeping this separate allows easier unit testing
        // Your type mappings here
    }
}
[assembly: OwinStartup(typeof(UnityTest.BusinessLayer.Api.ApiStartup))]
namespace UnityTest.BusinessLayer.Api
{
    public static HttpConfiguration Config { get; private set; }

    public partial class ApiStartup
    {
        public void Configuration(IAppBuilder app)
        {
            // IoC
            var container = UnityConfig.GetConfiguredContainer();                
            var resolver = new UnityHierarchicalDependencyResolver(container);  // Gets us scoped resolution            
            app.UseDependencyResolverScope(resolver);  // And for the OWIN

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

            // NB Must be before WebApiConfig.Register
            ConfigureAuth(app); //In App_Start ->Startup.Auth

            // See http://stackoverflow.com/questions/33402654/web-api-with-owin-throws-objectdisposedexception-for-httpmessageinvoker
            // and http://aspnetwebstack.codeplex.com/workitem/2091
#if SELFHOST
            // WebAPI configuration
            Config = new HttpConfiguration
            {
                DependencyResolver = resolver
            };

            WebApiConfig.Register(Config);

            app.UseWebApi(Config);
#else
            GlobalConfiguration.Configuration.DependencyResolver = resolver;
            // http://stackoverflow.com/questions/19907226/asp-net-webapi-2-attribute-routing-not-working
            // Needs to be before RouteConfig.RegisterRoutes(RouteTable.Routes);
            GlobalConfiguration.Configure(WebApiConfig.Register);

            Config = GlobalConfiguration.Configuration;
#endif

            // Now do MVC configuration if appropriate
        }
    }
}
public static class AppBuilderExtensions
{
    public static IAppBuilder UseDependencyResolverScope(this IAppBuilder app, IDependencyResolver resolver)
    {
        return app.Use<DependencyResolverScopeMiddleware>(resolver);
    }
}

/// <summary>
/// Wraps middleware in a <see cref="IDependencyResolver"/> scope.
/// </summary>
public class DependencyResolverScopeMiddleware : OwinMiddleware
{
    private readonly IDependencyResolver resolver;

    public DependencyResolverScopeMiddleware(OwinMiddleware next, IDependencyResolver resolver) : base(next)
    {
        this.resolver = resolver;
    }

    public override async Task Invoke(IOwinContext context)
    {
        using (var scope = resolver.BeginScope())
        {
            context.SetDependencyScope(scope);
            await Next.Invoke(context);
        }
    }
}