Как заставить Ninject связываться с реализацией, в которой нет ссылки на - PullRequest
8 голосов
/ 05 июня 2011

Я использую NinjectMVC3 в моем проекте ASP.NET MVC3.

У меня есть 3 слоя

  • Foo.Web
  • Foo.Services
  • Foo.Data

Foo.Web ссылается на Foo.Services, но не Foo.Data.Один из моих сервисов выглядит следующим образом

public class FooService : IFooService
{
    private readonly IFooRepository _fooRepository;

    public FooService(IFooRepository fooRepository)
    {
        _fooRepository = fooRepository;
    }

    // ...
}

NinjectMVC3 выполняет этот метод начальной загрузки при запуске Foo.Web

private static void RegisterServices(IKernel kernel)
{
    kernel.Bind<IFooService>().To<FooService>();
    kernel.Bind<IFooRepository>().To<FooRepository>();
    // Foo.Web doesn't know what FooRepository is
}        

Как добавить зависимости FooServices из Foo.Web?

1 Ответ

7 голосов
/ 06 июня 2011

Чтобы вы указали в правильном направлении, я бы посоветовал вам взглянуть на луковую архитектуру .

Основная предпосылка заключается в том, что любой код может зависеть от более центральных слоев,В вашем сценарии (и это обычное явление для приложений MVC3, использующих шаблон Repository) ваш пользовательский интерфейс должен иметь ссылку на уровень служб, и допустимо иметь ссылку на уровень данных.

Если вы готовычтобы принять это (это жесткая пилюля, если вы работаете с классической N-уровневой установкой, я знаю), тогда ваша ситуация станет намного проще.

С Ninject вы теперь делаете что-то следующее:

В вашем файле NinjectMVC3.cs ваш CreateKernel становится

    /// <summary>
    /// Creates the kernel that will manage your application.
    /// </summary>
    /// <returns>The created kernel.</returns>
    private static IKernel CreateKernel()
    {
        var modules = new INinjectModule[]
                          {
                              new ServiceDIModule(),
                              new RepositoryDIModule()
                          };

        var kernel = new StandardKernel(modules);

        //RegisterServices(kernel); <-- Only if you have some custom binding 
        //                              that are UI specific
        return kernel;
    }

Теперь, на вашем уровне сервисов, вы добавляете ссылку на Ninject (просто Ninject через NuGet, а не MVC3 dropin через NuGet)и добавьте то, что я назвал выше ServiceDIModule, которое выглядит следующим образом:

using Ninject.Modules;

namespace MyServiceLayer
{
    public class ServiceDIModule : NinjectModule
    {
        public override void Load()
        {
            //Bind Services
            Bind<IPracticeService>().To<PracticeService>().InRequestScope();
        }
    }
}

, и вы повторяете тот же процесс для инъекций уровня данных, которые у вас могут быть (UnitofWork, DatabaseFactory, IFooRepository и т.1018 *

Теперь у вас есть доступ ко всем привязкам, которые вам нужны, заранее.Итак, ваш вопрос ко мне действительно сводится к изменению мышления.Если вы можете принять (неохотно или иначе) концепцию луковицы, ваш сценарий решается сам собой.

Вы также можете проверить Project Silk и CodeCampServer .Они оба в некоторой степени реализуют концепцию «лука» (Шелк наверняка, я смотрю на решение прямо сейчас, и веб-проект пользовательского интерфейса содержит ссылку на проект данных, который содержит все Repos)

Позвольтея знаю, что вы думаете.

...