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

nel*_*ant 80 asp.net webforms ninject

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

Joe*_*zer 79

以下是将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;
        }
Run Code Online (Sandbox Code Playgroud)

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>();
        }   
Run Code Online (Sandbox Code Playgroud)

在此示例中,无论何处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);
            }
Run Code Online (Sandbox Code Playgroud)

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; }     
Run Code Online (Sandbox Code Playgroud)

第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);
Run Code Online (Sandbox Code Playgroud)

在您的JavaScript中,您需要引用标准服务 - Company.Web.Services.YourWebService.GetProductivity(user, onSuccess)而不是PageMethods.GetProductivity(user, onSuccess).

我发现的唯一其他问题是将对象注入用户控件.虽然可以使用Ninject功能创建自己的基本UserControl,但我发现将属性添加到用户控件以获取所需对象并在容器页面中设置Property更快.我认为开箱即用的支持UserControls是在Ninject"待办事项"列表中.

添加Ninject非常简单,它是一个雄辩的IoC解决方案.很多人喜欢它,因为没有Xml配置.它还有其他有用的"技巧",比如只用Ninject语法将对象转换为Singletons Bind<ILogger>().To<WebLogger>().InSingletonScope().没有必要将WebLogger更改为实际的Singleton implmentation,我喜欢这样.

  • 我忘了从Global.asax.cs文件的Application_Start方法中调用超类型的方法NinjectHttpApplication.Application_Start.当我这样做时工作,否则它会破裂. (3认同)
  • 这似乎已经过时了.NuGet包,ninject.web,包含一些引导应用程序的代码,是否需要直接从NinjectHttpApplication继承? (2认同)

Jas*_*son 68

随着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. 在页面上使用属性注入

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>();
    } 
Run Code Online (Sandbox Code Playgroud)

默认

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());
    }
}
Run Code Online (Sandbox Code Playgroud)

的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());
    }
}
Run Code Online (Sandbox Code Playgroud)

楷模

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";
    }
}
Run Code Online (Sandbox Code Playgroud)

输出窗口的结果

I am a model 1
From master: I am a model 1
Run Code Online (Sandbox Code Playgroud)

  • 嗨,杰森.我无法让它工作,所以我想知道这是否完全破坏?我可以看到NinjectHttpModule在运行时加载,但没有注入.你能想到出现这种情况的原因吗? (5认同)
  • 很好的例子谢谢它适用于页面/母版页,但不适用于Asmx.我怎样才能让它在Asmx上运行?谢谢. (3认同)

Ada*_*ell 12

由于一个开放的bug,这里的答案目前无效.以下是使用客户httpmodule注入页面和控件而不需要继承ninject类的@Jason步骤的修改版本.

  1. 创建一个新的ASP.NET WebForms项目
  2. 使用NuGet添加Ninject.Web库
  3. 在App_Start/NinjectWebCommon.cs/RegisterServices方法中注册自定义绑定
  4. 添加InjectPageModule并在NinjectWebCommon中注册
  5. 在页面上使用属性注入

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;
}
Run Code Online (Sandbox Code Playgroud)

NinjectWebCommon/RegisterServices

    private static void RegisterServices(IKernel kernel)
    {
        kernel.Bind<IHttpModule>().To<InjectPageModule>();
        kernel.Bind<IAmAModel>().To<Model1>();

    } 
Run Code Online (Sandbox Code Playgroud)

默认

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());
    }
}
Run Code Online (Sandbox Code Playgroud)

的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());
    }
}
Run Code Online (Sandbox Code Playgroud)

楷模

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";
    }
}
Run Code Online (Sandbox Code Playgroud)

输出窗口的结果

I am a model 1
From master: I am a model 1
Run Code Online (Sandbox Code Playgroud)

  • 请注意,对于没有母版页的页面,这会失败.我修改了NinjectWebCommon:`if(currentPage.Master!= null){this.lazyKernel().Inject(currentPage.Master); }` (4认同)

nel*_*ant 8

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

  1. 在Global.asax上实现NinjectHttpApplication.对于内核,通过实现NinjectModule传递它.
  2. 在代码隐藏的每个Web表单页面加载事件上,实现Ninject.Web.PageBase.在其上添加[Inject]过滤器添加实例类.

有关更详细的示例,以下是我发现的一些有用链接:

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

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

  • @nellbryant这两个链接现在已经死了. (7认同)

jmp*_*pcm 0

查看 Steve Sanderson (Apress) 所著的《Pro ASP.NET MVC 2 Framework,第 2 版》一书。作者使用 Ninject 来连接数据库。我认为您可以使用这些示例并根据您的需要进行调整。