如何在asp.net Web窗体上实现Ninject或DI?

时间:2011-02-08 13:36:21

标签: asp.net webforms ninject

有很多例子可以让它在MVC应用程序上运行。它是如何在Web表单上完成的?

7 个答案:

答案 0 :(得分:78)

以下是将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语法将对象转换为Singletons - Bind<ILogger>().To<WebLogger>().InSingletonScope()。没有必要将WebLogger更改为实际的Singleton implmentation,我喜欢这个。

答案 1 :(得分:67)

随着Ninject v3.0的发布(截至2012年4月12日),它变得更容易了。注入是通过HttpModule实现的,因此不需要让您的页面继承自定义的Page / MasterPage。以下是快速加标的步骤(和代码)。

  1. 创建新的ASP.NET WebForms项目
  2. 使用NuGet添加Ninject.Web库(这也将关闭Ninject.Web.Common和Ninject库)
  3. 在App_Start / NinjectWebCommon.cs / RegisterServices方法中注册自定义绑定
  4. 在您的网页上使用属性注入
  5. 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
    

答案 2 :(得分:11)

由于The answer here

open bug目前无效。以下是@Jason的一个修改版本的步骤,使用客户httpmodule注入页面和控件,而无需从ninject类继承。

  1. 创建新的ASP.NET WebForms项目
  2. 使用NuGet添加Ninject.Web库
  3. 在App_Start / NinjectWebCommon.cs / RegisterServices方法中注册自定义绑定
  4. 添加InjectPageModule并在NinjectWebCommon中注册
  5. 在您的网页上使用属性注入
  6. 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
    

答案 3 :(得分:8)

我认为这是在ASP.NET Web窗体上实现Ninject.Web的步骤。

  1. 在Global.asax上实施NinjectHttpApplication。对于内核,通过实现NinjectModule传递它。
  2. 在代码隐藏的每个Web表单页面加载事件上,实现Ninject.Web.PageBase。在其上添加[Inject]过滤器添加实例类。
  3. 有关更详细的示例,以下是我发现的一些有用链接:

    1。http://joeandcode.net/post/Ninject-2-with-WebForms-35

    2。http://davidhayden.com/blog/dave/archive/2008/06/20/NinjectDependencyInjectionASPNETWebPagesSample.aspx

答案 4 :(得分:4)

查看Ninject.Web扩展程序。它提供基础架构 https://github.com/ninject/ninject.web

答案 5 :(得分:0)

查看Steve Sanderson(Apress)的书“Pro ASP.NET MVC 2 Framework,2nd Edition”。作者使用Ninject连接数据库。我想你可以使用这些例子并根据你的需要进行调整。

答案 6 :(得分:0)

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>();
    }
}