Как я могу реализовать Ninject или DI на веб-формах asp.net? - PullRequest
79 голосов
/ 08 февраля 2011

Существует множество примеров того, как это работает в приложении MVC. Как это делается на веб-формах?

Ответы [ 7 ]

78 голосов
/ 25 мая 2011

Ниже приведены инструкции по использованию Ninject с веб-формами.

Step1 - Загрузки

Требуется две загрузки - Ninject-2.0.0.0-release-net-3.5 и расширения WebForm Ninject.Web_1.0.0.0_With.log4net (существует NLog альтернатива).

В веб-приложении должны быть ссылки на следующие файлы: Ninject.dll, Ninject.Web.dll, Ninject.Extensions.Logging.dll и Ninject.Extensions.Logging.Log4net.dll.

Шаг 2 - Global.asax

Класс Global должен быть производным от Ninject.Web.NinjectHttpApplication и реализовать CreateKernel(), который создает контейнер:

using Ninject; using Ninject.Web;

namespace Company.Web {
    public class Global : NinjectHttpApplication


        protected override IKernel CreateKernel()
        {
            IKernel kernel = new StandardKernel(new YourWebModule());
            return kernel;
        }

Конструктор StandardKernel занимает Module.

Шаг 3 - Модуль

Модуль, в данном случае YourWebModule, определяет все привязки, которые понадобятся веб-приложению:

using Ninject;
using Ninject.Web;

namespace Company.Web
{
    public class YourWebModule : Ninject.Modules.NinjectModule
    {

        public override void Load()
        {
            Bind<ICustomerRepository>().To<CustomerRepository>();
        }   

В этом примере, где бы ни указывался интерфейс ICustomerRepository, будет использоваться бетон CustomerRepository.

Шаг 4 - Страницы

После этого каждая страница должна наследоваться от Ninject.Web.PageBase:

  using Ninject;
    using Ninject.Web;
    namespace Company.Web
    {
        public partial class Default : PageBase
        {
            [Inject]
            public ICustomerRepository CustomerRepo { get; set; }

            protected void Page_Load(object sender, EventArgs e)
            {
                Customer customer = CustomerRepo.GetCustomerFor(int customerID);
            }

InjectAttribute -[Inject] - сообщает Ninject о необходимости ввода ICustomerRepository в свойство CustomerRepo.

Если у вас уже есть базовая страница, вам просто нужно получить базовую страницу для получения из Ninject.Web.PageBase.

Шаг 5 - Мастер-страницы

Неизбежно, у вас будут мастер-страницы, и для того, чтобы MasterPage мог получить доступ к внедренным объектам, вам нужно извлечь свою мастер-страницу из Ninject.Web.MasterPageBase:

using Ninject;
using Ninject.Web;

namespace Company.Web
{
    public partial class Site : MasterPageBase
    {

        #region Properties

        [Inject]
        public IInventoryRepository InventoryRepo { get; set; }     

Шаг 6 - Методы статической веб-службы

Следующая проблема не заключалась в возможности внедрения в статические методы. У нас было несколько Ajax PageMethods, которые явно статичны, поэтому мне пришлось перенести методы в стандартный веб-сервис. Опять же, веб-сервис должен быть производным от класса Ninject - Ninject.Web.WebServiceBase:

using Ninject;
using Ninject.Web;    
namespace Company.Web.Services
{

    [WebService(Namespace = "//tempuri.org/">http://tempuri.org/")]
    [WebServiceBinding(ConformsTo = WsiProfiles.BasicProfile1_1)]    
    [System.Web.Script.Services.ScriptService]
    public class YourWebService : WebServiceBase
    {

        #region Properties

        [Inject]
        public ICountbackRepository CountbackRepo { get; set; }

        #endregion

        [WebMethod]
        public Productivity GetProductivity(int userID)
        {
            CountbackService _countbackService =
                new CountbackService(CountbackRepo, ListRepo, LoggerRepo);

В вашем JavaScript вам нужно ссылаться на стандартную службу - Company.Web.Services.YourWebService.GetProductivity(user, onSuccess), а не PageMethods.GetProductivity(user, onSuccess).

Единственная другая проблема, которую я обнаружил, - это введение объектов в элементы управления пользователя. Хотя можно создать собственный базовый UserControl с возможностями Ninject, я обнаружил, что быстрее добавить свойство в пользовательский элемент управления для требуемого объекта и задать свойство на странице контейнера. Я думаю, что поддержка UserControls из коробки находится в списке «дел» Ninject.

Добавление Ninject довольно просто и является красноречивым решением IoC. Многим это нравится, потому что нет конфигурации Xml. У него есть другие полезные «уловки», такие как превращение объектов в синглтоны только с синтаксисом Ninject - Bind<ILogger>().To<WebLogger>().InSingletonScope(). Нет необходимости менять WebLogger на фактическую имплементацию Singleton, мне это нравится.

67 голосов
/ 12 апреля 2012

Это стало проще с выпуском Ninject v3.0 (по состоянию на 12.04.2012). Инъекция реализована с помощью HttpModule, поэтому нет необходимости наследовать ваши страницы от пользовательской страницы / MasterPage. Вот шаги (и код) для быстрого всплеска.

  1. Создание нового проекта ASP.NET WebForms
  2. Используйте NuGet для добавления библиотеки Ninject.Web (которая также приведет к сбоям библиотек Ninject.Web.Common и Ninject)
  3. Зарегистрируйте свои пользовательские привязки в методе App_Start / NinjectWebCommon.cs / RegisterServices
  4. Использование атрибутов на ваших страницах

NinjectWebCommon / RegisterServices

    /// <summary>
    /// Load your modules or register your services here!
    /// </summary>
    /// <param name="kernel">The kernel.</param>
    private static void RegisterServices(IKernel kernel)
    {
        kernel.Bind<IAmAModel>().To<Model1>();
    } 

По умолчанию

public partial class _Default : System.Web.UI.Page
{

    [Inject]
    public IAmAModel Model { get; set; }

    protected void Page_Load(object sender, EventArgs e)
    {
        System.Diagnostics.Trace.WriteLine(Model.ExecuteOperation());
    }
}

Site.Master

public partial class SiteMaster : System.Web.UI.MasterPage
{

    [Inject]
    public IAmAModel Model { get; set; }

    protected void Page_Load(object sender, EventArgs e)
    {
        System.Diagnostics.Trace.WriteLine("From master: " 
            + Model.ExecuteOperation());
    }
}

Модель

public interface IAmAModel
{
    string ExecuteOperation();         
}

public class Model1 : IAmAModel
{
    public string ExecuteOperation()
    {
        return "I am a model 1";
    }
}

public class Model2 : IAmAModel
{
    public string ExecuteOperation()
    {
        return "I am a model 2";
    }
}

Результаты из окна вывода

I am a model 1
From master: I am a model 1
11 голосов
/ 01 апреля 2014

Ответ здесь в настоящее время не работает из-за открытой ошибки . Вот модифицированная версия шагов @ Jason, использующих пользовательский httpmodule для внедрения в страницы и элементы управления без необходимости наследования от неполных классов.

  1. Создание нового проекта ASP.NET WebForms
  2. Используйте NuGet для добавления библиотеки Ninject.Web
  3. Зарегистрируйте свои пользовательские привязки в методе App_Start / NinjectWebCommon.cs / RegisterServices
  4. Добавьте InjectPageModule и зарегистрируйтесь в NinjectWebCommon
  5. Использовать вставку атрибутов на ваших страницах

InjectPageModule.cs

 public class InjectPageModule : DisposableObject, IHttpModule
{
    public InjectPageModule(Func<IKernel> lazyKernel)
    {
        this.lazyKernel = lazyKernel;
    }

    public void Init(HttpApplication context)
    {
        this.lazyKernel().Inject(context);
        context.PreRequestHandlerExecute += OnPreRequestHandlerExecute;
    }

    private void OnPreRequestHandlerExecute(object sender, EventArgs e)
    {
        var currentPage = HttpContext.Current.Handler as Page;
        if (currentPage != null)
        {
            currentPage.InitComplete += OnPageInitComplete;
        }
    }

    private void OnPageInitComplete(object sender, EventArgs e)
    {
        var currentPage = (Page)sender;
        this.lazyKernel().Inject(currentPage);
        this.lazyKernel().Inject(currentPage.Master);
        foreach (Control c in GetControlTree(currentPage))
        {
            this.lazyKernel().Inject(c);
        }

    }

    private IEnumerable<Control> GetControlTree(Control root)
    {
        foreach (Control child in root.Controls)
        {
            yield return child;
            foreach (Control c in GetControlTree(child))
            {
                yield return c;
            }
        }
    }

    private readonly Func<IKernel> lazyKernel;
}

NinjectWebCommon / RegisterServices

    private static void RegisterServices(IKernel kernel)
    {
        kernel.Bind<IHttpModule>().To<InjectPageModule>();
        kernel.Bind<IAmAModel>().To<Model1>();

    } 

По умолчанию

public partial class _Default : System.Web.UI.Page
{

    [Inject]
    public IAmAModel Model { get; set; }

    protected void Page_Load(object sender, EventArgs e)
    {
        System.Diagnostics.Trace.WriteLine(Model.ExecuteOperation());
    }
}

Site.Master

public partial class SiteMaster : System.Web.UI.MasterPage
{

    [Inject]
    public IAmAModel Model { get; set; }

    protected void Page_Load(object sender, EventArgs e)
    {
        System.Diagnostics.Trace.WriteLine("From master: " 
            + Model.ExecuteOperation());
    }
}

Модель

public interface IAmAModel
{
    string ExecuteOperation();         
}

public class Model1 : IAmAModel
{
    public string ExecuteOperation()
    {
        return "I am a model 1";
    }
}

public class Model2 : IAmAModel
{
    public string ExecuteOperation()
    {
        return "I am a model 2";
    }
}

Результаты из окна вывода

I am a model 1
From master: I am a model 1
8 голосов
/ 08 февраля 2011

Я думаю, что здесь приведены шаги для реализации Ninject.Web на веб-формах ASP.NET.

  1. Реализация приложения NinjectHttpApplication на Global.asax.Для ядра передайте его, реализовав NinjectModule.
  2. На каждом событии загрузки страницы веб-форм в коде позади, реализуйте Ninject.Web.PageBase.Добавьте экземпляр класса с фильтром [Inject] поверх него.

Для более подробного примера ниже приведены некоторые полезные ссылки, которые я нашел:

1. http://joeandcode.net/post/Ninject-2-with-WebForms-35

2. http://davidhayden.com/blog/dave/archive/2008/06/20/NinjectDependencyInjectionASPNETWebPagesSample.aspx

4 голосов
/ 08 февраля 2011

Посмотрите на расширение Ninject.Web.Обеспечивает базовую инфраструктуру https://github.com/ninject/ninject.web

0 голосов
/ 27 марта 2018
public IGoalsService_CRUD _context { get; set; }

Объект _context каким-то образом устанавливается равным нулю. Ниже приведены остальные настройки

public partial class CreateGoal : Page
{
    [Inject]
    public IGoalsService_CRUD _context { get; set; }
}

Для глобального файла

protected override IKernel CreateKernel()
{
    IKernel kernel = new StandardKernel(new Bindings());
    return kernel;
}

public class Bindings : NinjectModule
{
    public override void Load()
    {
        Bind<goalsetterEntities>().To<goalsetterEntities>();
        Bind<IGoalsService_CRUD>().To<GoalsService_CRUD>();
    }
}
0 голосов
/ 08 февраля 2011

Проверьте книгу "Pro ASP.NET MVC 2 Framework, 2-е издание" Стива Сандерсона (Apress). Автор использует Ninject для связи с базой данных. Я думаю, что вы можете использовать примеры и адаптировать их к вашим потребностям.

...