【发布时间】:2011-06-23 10:50:52
【问题描述】:
有很多例子可以让它在 MVC 应用程序上运行。它是如何在 Web 表单上完成的?
【问题讨论】:
有很多例子可以让它在 MVC 应用程序上运行。它是如何在 Web 表单上完成的?
【问题讨论】:
以下是将 Ninject 与 WebForms 一起使用的步骤。
第 1 步 - 下载
需要两个下载 - 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
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,定义了 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 继承:
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 步 - 静态 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 中,您需要引用标准服务 - Company.Web.Services.YourWebService.GetProductivity(user, onSuccess),而不是 PageMethods.GetProductivity(user, onSuccess)。
我发现的唯一其他问题是将对象注入用户控件。虽然可以使用 Ninject 功能创建自己的基本 UserControl,但我发现将属性添加到所需对象的用户控件并在容器页面中设置属性会更快。我认为支持开箱即用的 UserControls 在 Ninject“待办事项”列表中。
添加 Ninject 非常简单,它是一个雄辩的 IoC 解决方案。很多人喜欢它是因为没有 XML 配置。它还有其他有用的“技巧”,例如仅使用 Ninject 语法将对象转换为单例 - Bind<ILogger>().To<WebLogger>().InSingletonScope()。无需将 WebLogger 更改为实际的 Singleton 实现,我喜欢这样。
【讨论】:
随着 Ninject v3.0 的发布(截至 2012 年 4 月 12 日),它变得更容易了。注入是通过 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
【讨论】:
App_Start 中有一个NinjectWeb.cs。您初始化 Ninject 的代码必须放在这个文件中。如果它在一个单独的文件中(例如NinjectWebCommon.cs 它将不起作用)。如果您使用 NuGet 安装 Ninject.Web 的时间晚于其他 Ninject 包,则会发生这种情况。
The answer here 目前由于open bug 而无法工作。这是 @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); }
我认为这里是在 ASP.NET Web 窗体上实现 Ninject.Web 的步骤。
有关更详细的示例,以下是我找到的一些有用的链接:
【讨论】:
查看 Steve Sanderson (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>();
}
}
【讨论】: