Как я могу реализовать Ninject или DI на веб-формах asp.net?
Существует множество примеров того, как это работает в приложении MVC. Как это делается на веб-формах?
7 ответов
Вот шаги, чтобы использовать 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 - Мастер страницы
Неизбежно, у вас будут мастер-страницы, и для того, чтобы Master Page мог получить доступ к внедренным объектам, вам нужно извлечь свою мастер-страницу из 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, мне это нравится.
Это стало проще с выпуском Ninject v3.0 (по состоянию на 12.04.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
Ответ здесь в настоящее время не работает из-за открытой ошибки. Вот модифицированная версия шагов @Jason, использующих пользовательский httpmodule для внедрения в страницы и элементы управления без необходимости наследования от недействительных классов.
- Создать новый проект 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
Я думаю, что здесь приведены шаги для реализации Ninject.Web на веб-формах ASP.NET.
- Реализуйте NinjectHttpApplication в Global.asax. Для Ядра передайте его, реализовав NinjectModule.
- На каждом событии загрузки страницы веб-форм в коде позади, реализуйте Ninject.Web.PageBase. Добавьте класс экземпляра с фильтром [Inject] поверх него.
Для более подробного примера ниже приведены некоторые полезные ссылки, которые я нашел:
Посмотрите на расширение Ninject.Web. Предоставляет базовую инфраструктуру https://github.com/ninject/ninject.web
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>();
}
}
Проверьте книгу "Pro ASP.NET MVC 2 Framework, 2-е издание" Стива Сандерсона (Apress). Автор использует Ninject для связи с базой данных. Я думаю, что вы можете использовать примеры и адаптировать их к вашим потребностям.