C# Unity.WebApi |确保控制器具有无参数公共构造函数

C# Unity.WebApi |确保控制器具有无参数公共构造函数,c#,asp.net-web-api,dependency-injection,inversion-of-control,unity-container,C#,Asp.net Web Api,Dependency Injection,Inversion Of Control,Unity Container,我正在ASP.NET WebApi解决方案中使用Unity.WebApi NuGet包(Unity 4.0.1和Unity.WebApi 5.2.3)。我面临的问题是,当尝试运行代码时,我会得到错误:确保控制器具有无参数公共构造函数。我在这里搜索过类似的线程,但找不到任何与我的问题相匹配的线程 请不要只说“添加一个无参数构造函数”,因为这表明你显然不知道什么是IoC,为什么这句话毫无意义,违背了IoC的宗旨。我之所以这么说,是因为我在很多其他线程上都看到了这一点 这是我的Startup.cs(我

我正在ASP.NET WebApi解决方案中使用Unity.WebApi NuGet包(Unity 4.0.1和Unity.WebApi 5.2.3)。我面临的问题是,当尝试运行代码时,我会得到错误:
确保控制器具有无参数公共构造函数
。我在这里搜索过类似的线程,但找不到任何与我的问题相匹配的线程

请不要只说“添加一个无参数构造函数”,因为这表明你显然不知道什么是IoC,为什么这句话毫无意义,违背了IoC的宗旨。我之所以这么说,是因为我在很多其他线程上都看到了这一点

这是我的Startup.cs(我使用的是Owin,所以我没有全局.asax):

这是我的UnityConfig.cs:

public static class UnityConfig {
    public static void RegisterComponents() {
        var container = new UnityContainer();
            // Register controller
            container.RegisterType<MyController>();

            // Register interface
            container.RegisterType<IService, Service>();

            GlobalConfiguration.Configuration.DependencyResolver = new UnityDependencyResolver(container);
    }
}
编辑


我删除了using语句,因为无论using语句是否存在,人们都很难理解问题的发生。

根据我的经验,出现这种情况时有两种不同的情况

一,。 确保可以解析
服务
构造函数中的所有参数。它是否有您尚未注册的依赖项

二,。 确保使用Web API注册Unity。像这样:

public static class WebApiConfig
{
    public static void Register(HttpConfiguration config)
    {
        // Routes and other stuff here...

        var container = IocContainer.Instance; // Or any other way to fetch your container.
        config.DependencyResolver = new UnityDependencyResolver(container);
    }
}
示例如下:

编辑1:

正如注释中提到的@NightOwl888,您不应该处置容器。注册是在容器上注册的,当容器被释放时,它将不知道如何解决依赖关系。这可能会导致您看到的错误

编辑2:

由于您正在使用Owin,您应该能够执行以下操作:

    public void Configuration(IAppBuilder appBuilder) 
    { 
      // Configure Web API for self-host. 
      HttpConfiguration config = new HttpConfiguration();
      config.DependencyResolver = new UnityDependencyResolver(
          UnityConfig.GetConfiguredContainer());

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

      appBuilder.UseWebApi(config); 
    }
并将您的UnityConfiguration更新为:

    public static class UnityConfig {
       public static IUnityContainer GetConfiguredContainer() {
            var container = new UnityContainer();
            // Register controller
            container.RegisterType<MyController>();

            // Register interface
            container.RegisterType<IService, Service>();

            //This is done in Startup instead.
            //GlobalConfiguration.Configuration.DependencyResolver = new UnityDependencyResolver(container);
            return container;
    }
}
公共静态类UnityConfig{
公共静态IUnityContainer GetConfiguredContainer(){
var container=new UnityContainer();
//寄存器控制器
container.RegisterType();
//寄存器接口
container.RegisterType();
//这是在启动时完成的。
//GlobalConfiguration.Configuration.DependencyResolver=新的UnityDependencyResolver(容器);
返回容器;
}
}
从这个来源:

在此方法中,HttpConfiguration.DependencyResolver设置为 UnityDependencyResolver实例。这是必要的,以便承包商 可以在webApi控制器中使用注入。这个 UnityDependencyResolver类与 Unity.WebApi.UnityDependencyResolver类。未使用Unity.WebApi 因为这是一个自托管的OWIN应用程序


dependencysolver
设置为启动时创建的
HttpConfiguration
,而不是
GlobalConfiguration.Configuration
,并确保所有服务构造函数都是公共的,希望这有助于确保也被注入的任何嵌套类型都被正确解析。即使嵌套类型解析不正确,您也会在控制器级别收到错误消息。

此问题的另一个可能调查路径和原因。我在全局异常处理程序上设置断点,并查看异常实例上的嵌套异常属性。我得到的错误是没有一个可访问的构造函数,这是真的,因为我想要注入的类型确实有一个私有构造函数(我正在重构一个单例)

因此,我刚刚将另一个指定为受保护,以快速解决问题

    public Repository() : this( ... ) { ... }

    // if need to make public, make sure that the dependency injection container
    // will choose the parameterless constructor;
    // Unity has had issues with that by default
    protected Repository(DbContext context) : base() { ... }
在我看来,Unity本可以找到“可调用”构造函数——因为它没有注册DbContext(或任何派生上下文)

请注意,默认情况下,
Unity
选择具有最大参数数的构造函数

因此,是的,也可以像前面所描述的那样用
InjectionConstructorAttribute
来修饰适当的构造函数,但是我的数据访问层中甚至没有
Unity
引用(我不想)


请告诉我这种行为在以后的版本中是否发生了变化。

不幸的是,这些答案对我都不起作用。我已经通过以下步骤使用了smoksnes提供的方法:


我的问题是通过使用特定于web api的unity软件包(unity.AspNet.WebApi)而不是Microsoft指南中描述的通用.net软件包解决的

你能分享服务类的详细信息吗?您是否缺少注册服务类所需的任何类?可能是您的容器在MVC实际使用之前就已经被释放了吗?它抛出这个错误是不符合逻辑的,但是可能。请尝试将
var container=new UnityContainer()
从using块中取出。否则没有要共享的详细信息。假设它所做的只是有一个打印“Hello World”的方法。夜猫子我最初是这么做的,所以事实并非如此。后来,在试图解决这个问题的过程中,出现了使用问题。我认为这是一个不可靠的事情,因为它是基于Owin的,但我不确定。@NightOwl888是正确的。将unity容器和http配置从使用语句中去掉。它们都在收到第一个web请求之前被处理。@TylerOhlsen无论是否存在USING,都会产生相同的错误结果。请参阅我回答夜猫子问题的评论。using语句是在这些问题发生之后出现的,它是在尝试解决问题的过程中添加的。不管是否有使用,我仍然看到同样的问题。另外,假设服务中没有任何内容,并且它的默认构造函数为空。或者如果你的imagi
    public static class UnityConfig {
       public static IUnityContainer GetConfiguredContainer() {
            var container = new UnityContainer();
            // Register controller
            container.RegisterType<MyController>();

            // Register interface
            container.RegisterType<IService, Service>();

            //This is done in Startup instead.
            //GlobalConfiguration.Configuration.DependencyResolver = new UnityDependencyResolver(container);
            return container;
    }
}
    public Repository() : this( ... ) { ... }

    // if need to make public, make sure that the dependency injection container
    // will choose the parameterless constructor;
    // Unity has had issues with that by default
    protected Repository(DbContext context) : base() { ... }