Ninject не внедряет и выбрасывает исключения с нулевой ссылкой - PullRequest
5 голосов
/ 09 марта 2011

Я новичок в Ninject, поэтому я уверен, что я что-то не так делаю, я просто не уверен, что.Я использую Ninject и Ninject.MVC3 в своем веб-приложении 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>();
    }
}

и изменил NinjectMVC3.csв папке AppStart, чтобы получить модуль при создании ядра:

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.И веб-приложение, и библиотека классов имеют ссылку на Ninject, а веб-приложение также имеет ссылку на Ninject.MVC3.Привязка и создание ядра происходят в веб-приложении.

Ответы [ 5 ]

3 голосов
/ 09 марта 2011

Во-первых, вы вызываете неправильный конструктор в вашем контроллере.Этот конструктор без параметров больше ничего не вызывает, и поэтому вы получаете нулевое исключение.Во-вторых, вы хотите провести рефакторинг вашего контроллера, чтобы не было прямых зависимостей.

Вы хотели бы сделать что-то вроде следующего:

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.

0 голосов
/ 09 марта 2011

Проблема в том, что когда вы создаете CachedCustomerRepository в своем методе действия, вы просто создаете его экземпляр самостоятельно и не получаете Ninject для его создания и последующего внедрения его зависимостей.

Что вам нужно сделать, это использовать инжектор конструктора для контроллера.

* 1006 Е.Г. *

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>, который нужно ввести в MyController.

0 голосов
/ 09 марта 2011

Убедитесь, что вы звоните DependencyResolver.SetResolver(CreateKernel());, чтобы сообщить MVC, какой преобразователь вы собираетесь использовать.Возможно, вы звоните, но я не увидел его в вашем посте, иначе ваш код выглядит нормально.

0 голосов
/ 09 марта 2011

Чтобы получить полное преимущество от использования IOC, вы должны реорганизовать зависимость CachedCustomerRepository от вашего класса контроллера.Вам нужно будет добавить новую привязку к вашему модулю Ninject.Эта привязка должна будет использовать контекст, чтобы определить, связывает ли она «IRepository» с экземпляром CachedCustomerRepository или с экземпляром контроллера MVC.Как только вы укажете это, Ninject создаст и будет управлять временем жизни обоих объектов.

0 голосов
/ 09 марта 2011

Вы сделали класс в Global.asax наследовать NinjectHttpApplication?

...