我是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()
{
}
}
现在我有两个独立的存储库,一个需要注入数据库存储库的缓存版本:
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());
}
它在我的_repository.GetAll()
中的CachedCustomerRepository
行爆炸。
我设置了一个断点,以确保CreateKernel()
正在执行并获取绑定,它就是这样。我只是不确定注射为什么没有发生。另一方面,我不知道它是否重要,IRepository,Repositories和具体类型都在一个单独的类库中,并在mvc3 Web应用程序中引用。 Web应用程序和类库都引用了Ninject,Web应用程序也引用了Ninject.MVC3。绑定和内核创建都在Web App中进行。
答案 0 :(得分:3)
首先,您在控制器中调用了错误的构造函数。这个无参数构造函数不会调用任何其他东西,这就是你得到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模块中连接它。
答案 1 :(得分:0)
您是否已在Global.asax
继承了NinjectHttpApplication
?
答案 2 :(得分:0)
确保您正在调用DependencyResolver.SetResolver(CreateKernel());
以告知MVC您将使用哪个解析器。您可能正在调用它,但我没有在您的帖子中看到它 - 否则您的代码看起来很好。
答案 3 :(得分:0)
要获得使用IOC的全部好处,您应该从控制器类重构CachedCustomerRepository依赖项。您需要向Ninject模块添加新绑定。此绑定需要使用上下文来确定它是否将“IRepository”绑定到CachedCustomerRepository实例或MVC Controller实例。一旦你有了这个因素,那么Ninject将创建和管理两个对象的生命周期。
答案 4 :(得分:0)
问题在于,当你在动作方法中创建CachedCustomerRepository
时,你只是自己实例化它并且你没有让Ninject为你实例化它并随后注入它的依赖项。
你应该做的是为控制器使用构造函数注入。
E.g。
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>
注入需要注入IRepository<Customer>
的{{1}}。