1

我的 ASP .NET MVC 应用程序中有一个奇怪的问题。我有一些控制器和一些控制器IHelper,它是Helper这个控制器的实现。当我像下面这样使用这个助手时:

public ActionResult SomeAction()
{
    var hepler = new Helper();
    helper.DoStuff();
    ...
}

一切都好。但是当我尝试将此帮助器作为控制器的属性注入时:

public IHelper Helper { private get; set; }
...    
public ActionResult SomeAction()
    {            
        Helper.DoStuff();
        ...
    }

在我的 IoC 配置类中,我有:

ObjectFactory.Initialize(x =>
          {
              // Helpers
              x.For<IHelper>().Use<Helper>();              
              ...
              x.FillAllPropertiesOfType<IHelper>().Use<Helper>();
              ...
          }

问题是我在 IoC 配置类中使用 IoC 模式初始化了许多不同的助手、管理器、存储库和其他东西,并成功地注入到我的每个控制器中。但是当我尝试注入这个时Helper,我得到:

InvalidOperationException: An error occurred when trying to create a controller of type 'MyController'. Make sure that the controller has a parameterless public constructor.

我知道问题出在 IoC 中,Helper因为我用 google 搜索了这个Helper从 IoC 配置类中删除,像使用它一样var hepler = new Helper();,一切正常。但我不明白问题出在哪里?以前有人见过这样的问题吗?我什至无法理解如何确保控制器具有无参数的公共构造函数,并且当一切都适用于另一个助手等时,控制器属性之一的 IoC 初始化可以相关联。

编辑
_ 我正在使用 StructureMap IoC 框架和 ASP .NET MVC 4.0。

4

1 回答 1

4

对于初学者,您实际上并没有在这里使用依赖注入:

public IHelper Helper { private get; set; }
...    
public ActionResult SomeAction()
{
    var hepler = new Helper();
    helper.DoStuff();
    ...
}

你已经创建了一个 type 的属性IHelper,也许你的 IoC 框架甚至试图用一个实现来填充那个属性,但是在你的 action 方法中你仍然只是直接实例化一个实例Helper而不使用注入的属性,所以你仍然有对Helper而不是的硬依赖IHelper

更重要的是,您遇到的错误很可能取决于您使用的 IoC 框架和您使用的 ASP.NET MVC 版本。IoC看起来可能是 StructureMap,是这样吗?对于 MVC,它是哪个版本?

不同版本的 ASP.NET MVC 在其控制器构造函数中处理依赖关系解析的方式不同。例如,在 MVC 4 应用程序中,您可以创建 an 的实现IDependencyResolver并将其用于控制​​器。像这样的东西:

public class DomainDependencyResolver : IDependencyResolver
{
    private readonly IoCContainer Container;

    public DomainDependencyResolver(IoCContainer container)
    {
        Container = container;
    }

    public object GetService(Type serviceType)
    {
        if (serviceType.IsAbstract || serviceType.IsInterface)
            return Container.TryGetInstance(serviceType);
        else
            return Container.GetInstance(serviceType);
    }

    public IEnumerable<object> GetServices(Type serviceType)
    {
        return Container.GetAllInstances()
                        .Where(s => s.GetType() == serviceType);
    }
}

这使用了一个通用IoCContainer实例(类似于 Common Service Locator),但如果您只想直接使用您的 IoC 实现,那可能没问题。主要是实现GetServiceGetServices以便您的 IoC 容器返回任何请求类型的实现。然后,您将设置 ASP.NET MVC 以在应用程序启动(in )中为其控制器使用此依赖关系解析器实现Global.asax.cs

DependencyResolver.SetResolver(new DomainDependencyResolver(IoCContainerFactory.Current));

您唯一需要更改的是对 IoC 容器的引用。我正在使用我自己的通用版本,它是类型并且在一个IoCContainer名为. 您将使用您正在使用的任何框架,因此您只需要更改依赖解析器实现的构造函数以匹配您要传递的任何内容。CurrentIoCContainerFactory

于 2013-03-19T11:30:53.937 回答