2013-03-19 77 views
1

我在我的ASP .NET MVC应用程序中有奇怪的问题。我有一些控制器和一些IHelper和它的执行Helper这个控制器。当我使用如下的帮手:为什么IoC对控制器的创建有影响,以及如何解决?

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

每件事情都可以。但是,当我尝试注入这个帮助的属性控制器:

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

,并在我的IOC配置I类有:

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

事情是我有不同的助理,经理,仓库的LOT以及在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. 

我知道,这个问题是在国际奥委会和在此Helper因为我GOOGLE了this,从IOC配置类中删除Helper,用它像var hepler = new Helper();,一切运行良好。但我不明白是什么问题?有没有人看到过这个问题?我甚至不能understan如何确保控制器具有一个无参数的公共构造函数和控制器性能之一IoC的初始化可以与当一切的伟大工程的另一个助手等

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

+0

这可能有助于提及您正在使用StructureMap。 – 2013-03-19 11:33:05

+0

不确定你正在使用哪个IoC系统,但是你是否尝试过使用'set'' public'而不是'private'? – 2013-03-19 11:35:17

+0

我刚刚注意到这一点......它是'get',它是私人的,而不是'set'。这甚至会工作吗?由于该财产甚至没有被使用,目前尚不清楚其意图。 – David 2013-03-19 11:44:03

回答

4

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

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

您已经创建IHelper类型的属性,也许你的IoC框架,甚至还试图填充该属性与实施,但在您的操作方法中,您仍然只是直接实例化一个Helper的实例而不使用注入属性,因此您仍然对Helper而不是IHelper有很强的依赖性。

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

不同版本的ASP.NET MVC在其控制器构造函数中处理依赖关系解析的方式不同。例如,在MVC 4应用程序中,您可以创建一个实现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实例(类似常见的服务定位器),但如果你只是想使用IoC实现直接这可能是罚款。主要是实现GetServiceGetServices,以便您的IoC容器返回任何请求类型的实现。你会设置ASP。NET MVC利用其在应用程序启动控制器此依赖解析器实现(Global.asax.cs):

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

你不得不改变还有就是参考IoC容器的唯一的事。我正在使用我自己的通用版本,该版本的类型为IoCContainer,位于IoCContainerFactory上的静态属性为Current。您将使用您正在使用的任何框架,因此您只需要更改依赖解析器实现的构造函数,以匹配您要传递的任何内容。

+1

准确!在解析Controller实例时,ASP.NET MVC需要无参数构造函数来创建控制器或调用“DependencyResolver”。另一个为StructureMap制作的自定义解析器可以在这个问题中找到:http://stackoverflow.com/questions/4706776/how-to-configure-dependency-injection-with-asp-net-mvc-3-rtm – Tallmaris 2013-03-19 11:54:59

相关问题