问题 使用属性注入而不是构造函数注入


长话短说,我正在尝试将ELMAH用于MVC 2和Ninject,我需要使用无参数构造函数。我在这里创建了一篇关于它的帖子: 在Ninject中使用无参数控制器构造函数?

我被建议使用属性注入而不是构造函数注入。所以我离开了这个:

public class DepartmentsController : Controller
{
    private IDepartmentsRepository departmentsRepository;

    public DepartmentsController(IDepartmentsRepository departmentsRepository)
    {
        this.departmentsRepository = departmentsRepository;
    }

    ...
}

对此:

public class DepartmentsController : Controller
{
    private IDepartmentsRepository _departmentsRepository;

    [Inject]
    public IDepartmentsRepository DepartmentsRepository
    {
        get { return _departmentsRepository; }
        set { _departmentsRepository = value; }
    }

    ...
}

但在我的其他控制器函数中,无论我是否尝试访问DepartmentsRepository或_departmentsRepository,我都得到了 你调用的对象是空的 我尝试访问它时出错。

我还需要做些什么吗?


9587
2018-02-02 02:00


起源

你正在用吗 Ninject.Web.Mvc? - Daniel T.
等什么?什么要求您使用无参数构造函数? - jfar
我有一个奇怪的问题,当属性具有特定名称时,不解决特定依赖项。如果重命名它可以正常工作,但所有其他依赖关系正常解析(并且相同的依赖关系在其他情况下解析为相同的属性名称)。我不知道为什么,但总是要尝试。 - Morten Christiansen
在我的课堂上,这是因为我试图在构造函数中访问我注入的属性。当然,在物体本身构造之前不能进行注射。 - neontapir
不确定为什么建议使用setter注入而不是构造函数注入。 Martin Fowler似乎建议构造函数超过setter。 - liang


答案:


我有类似的问题。看看我的问题: 使用Ninject和Membership.Provider

基本上当你初始化时 DepartmentsController 你需要注射this (即你的部门控制器进入你的Ninject核心。所以它是这样的:

public class DepartmentsController : Controller
{
  private IDepartmentsRepository _departmentsRepository;

  [Inject]
  public IDepartmentsRepository DepartmentsRepository
  {
    get { return _departmentsRepository; }
    set { _departmentsRepository = value; }
  }

  public DepartmentsController()
  {
    NinjectHelper.Kernel.Inject(this);
  }
}

在这种情况下,NinjectHelper获取当前的Ninject内核。


10
2018-02-02 09:49



这将有效,但使用ControllerFactory进行注入更好,控制器不必了解Ninject。 - dave thieben


尝试这样的事情:

的Global.asax.cs

        protected void Application_Start()
        {
            DependencyResolver.SetResolver(
                new MyDependencyResolver(
                    new StandardKernel(
                        new MyModule())));
            //...
        }

MyDependencyResolver.cs

    public class MyDependencyResolver : IDependencyResolver
    {
        private IKernel kernel;

        public MyDependencyResolver(IKernel kernel)
        {
            this.kernel = kernel;
        }

        public object GetService(Type serviceType)
        {
            return kernel.TryGet(serviceType);
        }

        public IEnumerable<object> GetServices(Type serviceType)
        {
            return kernel.GetAll(serviceType);
        }
    }

MyModule.cs

    public class MyModule : NinjectModule
    {
        public override void Load()
        {
            Bind<IDepartmentsRepository>().To<DepartmentsRepository>();
        }
    }

3
2018-02-02 13:10



这有助于回答这个问题? - dave thieben
@dave这可以解决他的'对象引用未设置为对象的实例'问题...对于Ninject.Web.Mvc,我没有尝试过。 - frennky


对象引用未设置异常可能有两个原因。

1)Ninject不知道如何将IDepartmentsRepository绑定到DepartmentsRepository的具体实现(我怀疑是这种情况)

2)如果您尝试访问控制器构造函数中的DepartmentsRepository属性,它将抛出异常(因为Ninject只能在构造对象后注入Property Dependencies)。

希望有所帮助。


2
2018-02-02 02:55





正如Daniel T.在上述评论中所发表的那样,你应该看看 Ninject.Web.Mvc。如果你在该项目中使用NinjectHttpApplication,它会为你自动装配一切,这样当NinjectControllerFactory构造一个新的控制器时,它会调用Inject()来填充属性注入。


0
2018-02-03 21:17