繁体   English   中英

Ninject不注入并抛出空引用异常

[英]Ninject not injecting and throwing null reference exceptions

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

我正在使用Repository模式:

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()
    {
    }
}

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

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()行上CachedCustomerRepository

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

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

您想要执行以下操作:

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就可以解决你的依赖了! Ninject的内核将被要求通过MVC创建一个带有IRepository<Customer>的控制器。 由于Ninject具有这种“绑定”,它将尝试为您实例化CustomerRepository

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

你是否在Global.asax继承NinjectHttpApplication的类?

确保你正在调用DependencyResolver.SetResolver(CreateKernel()); 为了告诉MVC你要使用哪个解析器。 您可能正在调用它,但我没有在您的帖子中看到它 - 否则您的代码看起来很好。

要获得使用IOC的全部好处,您应该从控制器类重构CachedCustomerRepository依赖项。 您需要向Ninject模块添加新绑定。 此绑定需要使用上下文来确定它是否将“IRepository”绑定到CachedCustomerRepository实例或MVC Controller实例。 一旦你有了这个因素,那么Ninject将创建和管理两个对象的生命周期。

问题是当你在action方法中创建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<Customer>注入到需要注入MyControllerIRepository<Customer>中。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM