Есть много примеров того, как это работало в приложении MVC. Как это делается в веб-формах?
Есть много примеров того, как это работало в приложении MVC. Как это делается в веб-формах?
Ответы:
Вот шаги по использованию 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
Класс 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, мне это нравится.
Это стало проще с выпуском Ninject v3.0 (от 12.04.2012). Внедрение осуществляется через HttpModule, поэтому нет необходимости наследовать ваши страницы от настраиваемой Page / MasterPage. Вот шаги (и код) для быстрого всплеска.
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
NinjectWeb.cs
в App_Start
. Ваш код для инициализации Ninject должен находиться в этом файле. Если он в отдельном файле (например NinjectWebCommon.cs
, не сработает). Это может произойти, если вы установите Ninject.Web позже, чем другие пакеты Ninject, использующие NuGet.
Ответ здесь в настоящее время не работает из-за открытой ошибки . Вот модифицированная версия шагов @Jason с использованием клиентского httpmodule для внедрения в страницы и элементы управления без необходимости наследования от классов ninject.
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
if (currentPage.Master!=null) { this.lazyKernel().Inject(currentPage.Master); }
Я думаю, вот шаги по реализации Ninject.Web в веб-формах ASP.NET.
Для более подробного примера ниже приведены некоторые полезные ссылки, которые я нашел:
Взгляните на расширение Ninject.Web. Он предоставляет базовую инфраструктуру https://github.com/ninject/ninject.web
Посмотрите книгу Стива Сандерсона (Apress) "Pro ASP.NET MVC 2 Framework, 2nd Edition". Автор использует Ninject для подключения к базе данных. Я думаю, вы можете использовать примеры и адаптировать их к своим потребностям.
public IGoalsService_CRUD _context { get; set; }
Для объекта _context каким-то образом устанавливается значение null. Ниже приведены остальные настройки.
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>();
}
}