Как я могу реализовать Ninject или DI в asp.net Web Forms?

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

Ответ 1

Ниже приведены шаги по использованию Ninject с WebForms.

Шаг 1 - Загрузки

Требуется две загрузки - 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

Глобальный класс должен получить от 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).

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

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

Ответ 2

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

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

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

Ответ 3

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

  • Внедрить NinjectHttpApplication в Global.asax. Для ядра передайте его, выполнив NinjectModule.
  • В каждом событии загрузки страницы веб-форм позади кода реализуется 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

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

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

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

Ответ 6

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