【问题标题】:Ninject not injecting and throwing null reference exceptionsNinject 不注入和抛出空引用异常
【发布时间】:2011-03-09 18:32:52
【问题描述】:

我是 Ninject 的新手,所以我确定这是我做错了,我只是不确定是什么。我在我的 MVC3 Web 应用程序中使用了 Ninject 和 Ninject.MVC3。这是我正在尝试做的一个示例。

我正在使用存储库模式:

public interface IRepository<T>
{
    T Get(object id);
    IList<T> GetAll();
    void Add(T value);
    void Update(T value);
    void Delete(T value);
}

对于具体类型:

public Customer
{
    public int Id { get; set; }
    public string Name { get; set; }
    public string Address { get; set; }

    public Customer()
    {
    }
}

现在我有 2 个独立的存储库,一个需要注入数据库存储库的缓存版本:

public CachedCustomerRepository : IRepository<Customer>
{
    private IRepository<Customer> _repository;

    public Customer Get(object id)
    {
        Customer cust = new Customer();
        IList<Customer> custs = GetAll();
        if (custs != null && custs.Count > 0)
            cust = custs.FirstOrDefault(c => c.Id == int.Parse(id.ToString()));

        return cust;
    }

    public IList<Customer> GetAll()
    {
        IList<Customer> custs = HttpRuntime.Cache["Customers"] as IList<Customer>;
        if (custs == null)
        {
            custs = _repository.GetAll();
            if (custs != null && custs.Count() > 0)
            {
                double timeout = 600000d;
                HttpRuntime.Cache.Insert("Customers", custs, null, DateTime.UtcNow.AddMilliseconds(timeout), System.Web.Caching.Cache.NoSlidingExpiration);
            }
            else
            {
                throw new NullReferenceException();
            }
        }

        return custs;
    }

    public void Add(Customer value)
    {
        throw new NotImplementedException();
    }

    public void Update(Customer value)
    {
        throw new NotImplementedException();
    }

    public void Delete(Customer value)
    {
        throw new NotImplementedException();
    }

    public CachedCustomerRepository()
    {
    }

    [Inject]
    public CachedCustomerRepository(IRepository<Customer> repository)
    {
        _repository = repository;
    }
}

public class CustomerRepository : IRepository<Customer>
{   
    public Customer Get(object id)
    {
        Customer cust = new Customer();
        IList<Customer> custs = GetAll();
        if (custs != null && custs.Count > 0)
            cust = custs.FirstOrDefault(c => c.Id == int.Parse(id.ToString()));

        return cust;
    }

    public IList<Customer> GetAll()
    {
        //Customer retrieval code
    }

    public void Add(Customer value)
    {
        throw new NotImplementedException();
    }

    public void Update(Customer value)
    {
        throw new NotImplementedException();
    }

    public void Delete(Customer value)
    {
        throw new NotImplementedException();
    }

    public CachedCustomerRepository()
    {
    }
}

我这样设置了一个 NinjectModule:

public class ServiceModule : NinjectModule
{
    public override void Load()
    {
        Bind<IRepository<Customer>>().To<CustomerRepository>();
    }
}

并且我在创建内核时修改了AppStart文件夹中的NinjectMVC3.cs来获取模块:

private static IKernel CreateKernel()
{
    var kernel = new StandardKernel(new ServiceModule());
    RegisterServices(kernel);
    return kernel;
}

在我的控制器中,我正在使用这个:

public ViewResult Index()
{
    IRepository<Customer> custRepo = new CachedCustomerRepository();
    return View(custRepo.GetAll());
}

它在我的CachedCustomerRepository 中的_repository.GetAll() 线上爆炸了。

我设置了一个断点以确保CreateKernel() 正在执行并获取绑定,它就是这样。我只是不确定为什么注射没有发生。另一方面,我不知道它是否重要,IRepository、Repositories 和具体类型位于单独的类库中,并在 mvc3 Web 应用程序中引用。 Web 应用程序和类库都引用了 Ninject,Web 应用程序也引用了 Ninject.MVC3。绑定和内核创建都在 Web App 中进行。

【问题讨论】:

  • +1 表示每个人在第一次学习依赖注入时所经历的挫折。

标签: c# asp.net-mvc-3 ninject


【解决方案1】:

首先,您在控制器中调用了错误的构造函数。这个无参数的构造函数不调用任何其他东西,这就是你得到空异常的原因。其次,你想重构你的控制器,这样就没有直接的依赖关系。

您需要执行以下操作:

public class SomeController
{
    private readonly IRepository<Customer> repo;

    public SomeController(IRepository<Customer> repo)
    {
        this.repo = repo;
    }

    public ViewResult Index()
    {
        return View(this.repo.GetAll());
    }
}

这样,Ninject 会为您解决依赖关系! MVC 将要求 Ninject 的内核使用IRepository&lt;Customer&gt; 创建一个控制器。由于 Ninject 有这个“绑定”,它会尝试为你实例化 CustomerRepository

另外,您为什么要创建“CachedRepository”?我真的,真的认为你过早地优化了这个。老实说,您只需要一个 CustomerRepository,然后将其连接到 Ninject 模块中。

【讨论】:

  • 我最终做的是为 repo 创建一个属性并将其注入,因为将来我将在控制器中拥有多个 repo 类型,并且我也对其应用了一个自定义属性。这让我可以使用上下文属性绑定。
  • @Alexander - 虽然属性注入当然是可能的,但它通常不受欢迎。要添加更多存储库依赖项,您只需添加另一个构造函数参数。您在控制器中需要什么样的上下文绑定?无论如何,我很高兴您能够解决您的问题。干杯!
  • 也很高兴知道,我没有意识到财产注入是不受欢迎的。
【解决方案2】:

你有没有让Global.asax中的类继承NinjectHttpApplication

【讨论】:

  • 我认为使用 Ninject.MVC3 2.2.1.0 如果您使用的是 AppStart\NinjectMVC3.cs,则不必这样做
  • @Alexander Kahoun:很有可能;看起来距离我上次使用 Ninject 已经有点太久了......
【解决方案3】:

确保您调用 DependencyResolver.SetResolver(CreateKernel()); 以告知 MVC 您将使用哪个解析器。您可能正在调用它,但我在您的帖子中没有看到它 - 否则您的代码看起来不错。

【讨论】:

  • 是的,在我发布答案后我认为它确实如此。我还没有尝试过新的 AppStart Nuget 东西。感谢您的权威,尽管现在我会在未来知道:)
  • 不用担心 :) 新的东西使得与 MVC 的集成非常顺利。
【解决方案4】:

要获得使用 IOC 的全部好处,您应该从控制器类重构 CachedCustomerRepository 依赖项。您将需要为您的 Ninject 模块添加一个新绑定。此绑定将需要使用上下文来确定它是将“IRepository”绑定到 CachedCustomerRepository 实例还是 MVC 控制器实例。一旦你把它分解出来,然后 Ninject 将创建和管理这两个对象的生命周期。

【讨论】:

    【解决方案5】:

    问题在于,当您在操作方法中创建 CachedCustomerRepository 时,您只是在自己实例化它,并没有让 Ninject 为您实例化它并随后注入它的依赖项。

    你应该做的是为控制器使用构造函数注入。

    例如

    public class MyController : Controller
    {
        public IRepository<Customer> CustomerRepo { get; protected set; }
    
        public MyController(IRepository<Customer> customerRepo)
        {
            CustomerRepo = customerRepo;
        }
    
        public ViewResult Index()
        {
            return View(CustomerRepo.GetAll());
        }
    }
    

    不过,您的情况有点令人困惑,因为您将 IRepository&lt;Customer&gt; 注入到需要注入 MyControllerIRepository&lt;Customer&gt; 中。

    【讨论】:

      猜你喜欢
      • 2021-04-29
      • 2022-01-05
      • 1970-01-01
      • 2013-02-08
      • 2017-06-23
      • 2011-07-22
      • 2014-11-19
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多