【问题标题】:Dependency Injection Constructor Conflict依赖注入构造函数冲突
【发布时间】:2013-10-30 19:04:50
【问题描述】:

我有一个控制器,我想在构造函数中使用依赖注入,这是我的代码

    private readonly IHomeService _iHomeService;

    public HomeController(IHomeService iHomeService)
    {
        _iHomeService = iHomeService;
    }

    public HomeController()
    {

    }

当我删除没有任何参数的构造函数(第二个构造函数)时,我看到了这个错误:

No parameterless constructor defined

当我使用没有任何参数的构造函数时,我看到我的私有字段为 null(_iHomeService = null),因为程序使用了没有参数的构造函数。

如何解决依赖注入的这个问题?

【问题讨论】:

  • 你在使用像 Castle Windsor 这样的 IoC 容器吗?
  • 不,我不使用任何 Ioc 容器

标签: asp.net-mvc model-view-controller dependency-injection inversion-of-control


【解决方案1】:

好吧,要进行依赖注入,您需要使用框架或使用控制器工厂。

试试ninject

public class HomeController : Controller
{
    private readonly IWelcomeMessageService welcomeMessageService;

    public HomeController(IWelcomeMessageService welcomeMessageService)
    {
        this.welcomeMessageService = welcomeMessageService;
    }

    public void Index()
    {
        ViewModel.Message = this.welcomeMessageService.TodaysWelcomeMessage;
        return View();
    }
}

public class WelcomeMessageServiceModule : NinjectModule
{
    public override void Load()
    {
        this.Bind<IWelcomeMessageService>().To<WelcomeMessageService>();
    }
}

框架将控制控制器实例的创建并传递构造函数参数

【讨论】:

  • 你实际上不需要框架来做 DI,完全可以手动注入依赖。
  • @JoeR - 我已经更正了“你需要(!)使用框架或(!)使用控制器工厂。”
【解决方案2】:

听起来您希望HomeService 类自动被实例化并注入到控制器中。

使用像 Ninject 或 StructureMap 这样的 IoC 框架将为您做到这一点 - 一旦您设置好了。

如果您不想使用 IoC 框架,则需要在构造函数中手动实例化 HomeService

【讨论】:

    【解决方案3】:

    ASP.NET 使用ControllerFactory 按需实例化您的控制器。这个类要求你的控制器有一个无参数的构造函数,它可以用来创建它的一个实例。

    您需要使用依赖注入框架来创建控制器并注入所需的依赖。 ASP.NET has some dependency injection capability,但我知道这是有缺陷的。我建议使用Castle Windsor 来管理你的依赖注入。和ASP.NET集成的很好,有集成教程here

    如果你走这条路,你最终会得到一个控制器和服务的安装程序:

    public class Installer : IWindsorInstaller
    {
        public void Install(IWindsorContainer container, IConfigurationStore store)
        {
            container.Register(Classes.FromThisAssembly().BasedOn<IController>().LifestyleTransient());
            container.Register(Component.For<IHomeService>.ImplementedBy<HomeService>());
        }
    }
    

    ..还有一个新的ControllerFactory 来创建它们:

    public class WindsorControllerFactory : DefaultControllerFactory
    {
        private readonly IKernel _kernel;
    
        public WindsorControllerFactory(IKernel kernel)
        {
            _kernel = kernel;
        }
    
        public override void ReleaseController(IController controller)
        {
            _kernel.ReleaseComponent(controller);
        }
    
        protected override IController GetControllerInstance(RequestContext requestContext, Type controllerType)
        {
            if (controllerType == null)
            {
                throw new HttpException(404, string.Format("The controller for path '{0}' could not be found.", requestContext.HttpContext.Request.Path));
            }
            return (IController) _kernel.Resolve(controllerType);
        }
    }
    

    最后,您将创建一个容器并设置一个新的控制器工厂:

    var container = new WindsorContainer().Install(new Installer());
    var controllerFactory = new WindsorControllerFactory(_container.Kernel);
    ControllerBuilder.Current.SetControllerFactory(controllerFactory);
    

    您也可以使用NinjectStructureMap

    【讨论】:

      猜你喜欢
      • 2011-02-02
      • 2019-04-20
      • 1970-01-01
      • 1970-01-01
      • 2018-06-17
      • 1970-01-01
      • 2023-04-04
      • 1970-01-01
      相关资源
      最近更新 更多