如何在asp.net Web窗体上实现Ninject或DI?
在MVC应用程序上有很多例子。 它如何在Web窗体上完成?
以下是在WebForms中使用Ninject的步骤。
第一步 – 下载
有两个下载需要 – Ninject-2.0.0.0-release-net-3.5和WebForm扩展Ninject.Web_1.0.0.0_With.log4net (有一个NLog替代)。
需要在Web应用程序中引用以下文件:Ninject.dll,Ninject.Web.dll,Ninject.Extensions.Logging.dll和Ninject.Extensions.Logging.Log4net.dll。
第2步 – Global.asax
全局类需要从Ninject.Web.NinjectHttpApplication
派生,并实现CreateKernel()
,它创build容器:
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
,定义了Web应用程序将需要的所有绑定:
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
inheritance:
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步 – 主页
不可避免地,您将拥有母版页,并且允许母版页访问注入的对象,您将需要从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步 – 静态Web服务方法
接下来的问题是无法注入静态方法。 我们有几个Ajax PageMethods,它们显然是静态的,所以我不得不将这些方法移动到标准的Web服务中。 同样,Web服务需要从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中,您需要引用标准服务PageMethods.GetProductivity(user, onSuccess)
,而不是PageMethods.GetProductivity(user, onSuccess)
。
我发现唯一的其他问题是注入对象到用户控件。 尽pipe可以使用Ninjectfunction创build自己的基本UserControl,但是我发现将属性添加到所需对象的用户控件并在容器页面中设置属性会更快。 我认为支持UserControls是在Ninject“待办事项”列表中。
添加Ninject非常简单,它是一个雄辩的IoC解决scheme。 许多人喜欢它,因为没有Xmlconfiguration。 它还有其他有用的“技巧”,例如只用Ninject语法将对象转换为单例, Bind<ILogger>().To<WebLogger>().InSingletonScope()
。 没有必要把WebLogger改成实际的Singleton实现,我喜欢这个。
Ninject v3.0的发布变得更加简单(截至2012年4月12日)。 注入是通过HttpModule实现的,所以不需要让页面inheritance自定义的页面/母版页。 这里是一个快速秒杀的步骤(和代码)。
- 创build一个新的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来注入页面和控件,而不需要从ninject类inheritance。
- 创build一个新的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
我想这里是在ASP.NET Web窗体上实现Ninject.Web的步骤。
- 在Global.asax上实现NinjectHttpApplication 对于内核,通过实现NinjectModule来传递它。
- 在每个网页上形成页面加载事件后面的代码,实现Ninject.Web.PageBase。 在其上添加[Inject]filter的实例类。
更详细的例子,下面是我发现的一些有用的链接:
看看Ninject.Web扩展。 它提供了基础架构https://github.com/ninject/ninject.web
查阅Steve Sanderson(Apress)的书“Pro ASP.NET MVC 2 Framework,2nd Edition”。 作者使用Ninject来连接数据库。 我认为你可以使用这些例子,并根据你的需要进行调整。