it-swarm.com.de

Wie kann ich Ninject oder DI in asp.net Web Forms implementieren?

Es gibt viele Beispiele für die Arbeit an einer MVC-Anwendung. Wie wird es in Web Forms gemacht?

79
nellbryant

Hier sind die Schritte zur Verwendung von Ninject mit WebForms.

Schritt 1 - Downloads

Es sind zwei Downloads erforderlich - Ninject-2.0.0.0-release-net-3.5 und die WebForm-Erweiterungen Ninject.Web_1.0.0.0_With.log4net (es gibt eine NLog-Alternative).

Die folgenden Dateien müssen in der Webanwendung referenziert werden: Ninject.dll, Ninject.Web.dll, Ninject.Extensions.Logging.dll und Ninject.Extensions.Logging.Log4net.dll.

Schritt 2 - Global.asax

Die globale Klasse muss von Ninject.Web.NinjectHttpApplication abgeleitet sein und CreateKernel() implementieren, wodurch der Container erstellt wird:

using Ninject; using Ninject.Web;

namespace Company.Web {
    public class Global : NinjectHttpApplication


        protected override IKernel CreateKernel()
        {
            IKernel kernel = new StandardKernel(new YourWebModule());
            return kernel;
        }

Der Konstruktor StandardKernel verwendet eine Module.

Schritt 3 - Modul 

Das Modul, in diesem Fall YourWebModule, definiert alle Bindungen, die die Webanwendung benötigt:

using Ninject;
using Ninject.Web;

namespace Company.Web
{
    public class YourWebModule : Ninject.Modules.NinjectModule
    {

        public override void Load()
        {
            Bind<ICustomerRepository>().To<CustomerRepository>();
        }   

Wenn in diesem Beispiel auf die ICustomerRepository-Schnittstelle verwiesen wird, wird die konkrete CustomerRepository verwendet.

Schritt 4 - Seiten

Sobald dies erledigt ist, muss jede Seite von Ninject.Web.PageBase erben:

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

Der InjectAttribute -[Inject] - weist Ninject an, ICustomerRepository in die CustomerRepo-Eigenschaft einzuspeisen.

Wenn Sie bereits über eine Basisseite verfügen, müssen Sie lediglich Ihre Basisseite von Ninject.Web.PageBase ableiten lassen.

Schritt 5 - Masterseiten

Zwangsläufig verfügen Sie über Masterseiten. Damit eine MasterPage auf injizierte Objekte zugreifen kann, müssen Sie Ihre Masterseite von Ninject.Web.MasterPageBase ableiten:

using Ninject;
using Ninject.Web;

namespace Company.Web
{
    public partial class Site : MasterPageBase
    {

        #region Properties

        [Inject]
        public IInventoryRepository InventoryRepo { get; set; }     

Schritt 6 - Statische Webdienstmethoden

Das nächste Problem war, nicht in statische Methoden einspritzen zu können. Wir hatten ein paar Ajax PageMethods, die offensichtlich statisch sind. Daher musste ich die Methoden in einen Standard-Webdienst verschieben. Wieder muss der Webdienst von einer Ninject-Klasse abgeleitet werden - 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);

In Ihrem JavaScript müssen Sie auf den Standarddienst Company.Web.Services.YourWebService.GetProductivity(user, onSuccess) statt PageMethods.GetProductivity(user, onSuccess) verweisen.

Das einzige andere Problem, das ich fand, war das Injizieren von Objekten in die Benutzersteuerelemente. Es ist zwar möglich, ein eigenes Basis-UserControl mit Ninject-Funktionen zu erstellen, aber ich habe es schneller gefunden, dem Benutzersteuerelement eine Eigenschaft für das erforderliche Objekt hinzuzufügen und die Eigenschaft auf der Containerseite festzulegen. Ich denke, die Unterstützung von UserControls ist "on-do" auf der Ninject-To-Do-Liste.

Ninject hinzuzufügen ist ziemlich einfach und es ist eine eloquente IoC-Lösung. Viele Leute mögen es, weil es keine XML-Konfiguration gibt. Es hat andere nützliche "Tricks" wie das Umwandeln von Objekten in Singletons mit der Ninject-Syntax - Bind<ILogger>().To<WebLogger>().InSingletonScope(). Es besteht keine Notwendigkeit, WebLogger in eine tatsächliche Implementierung von Singleton umzuwandeln. Das gefällt mir.

78
Joe Ratzer

Mit der Veröffentlichung von Ninject v3.0 (Stand vom 12.12.2012) ist es einfacher geworden. Die Injektion wird über HttpModule implementiert, sodass Ihre Seiten nicht von einer benutzerdefinierten Seite/MasterPage erben müssen. Hier sind die Schritte (und der Code) für eine schnelle Spitze.

  1. Erstellen Sie ein neues ASP.NET WebForms-Projekt
  2. Verwenden Sie NuGet, um die Ninject.Web-Bibliothek hinzuzufügen (wodurch auch die Ninject.Web.Common- und Ninject-Bibliothek heruntergefahren wird).
  3. Registrieren Sie Ihre benutzerdefinierten Bindungen in der App_Start/NinjectWebCommon.cs/RegisterServices-Methode
  4. Verwenden Sie die Attributinjektion auf Ihren Seiten

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

Standard

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

Modelle

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";
    }
}

Ergebnisse aus dem Ausgabefenster

I am a model 1
From master: I am a model 1
67
Jason

Die Antwort hier funktioniert derzeit aufgrund eines open-Fehlers nicht. Hier ist eine modifizierte Version von @ Jasons Schritten, die ein Kunden-httpmodule zum Einfügen in Seiten und Steuerelemente verwendet, ohne von neun Objektklassen erben zu müssen .

  1. Erstellen Sie ein neues ASP.NET WebForms-Projekt
  2. Verwenden Sie NuGet, um die Ninject.Web-Bibliothek hinzuzufügen 
  3. Registrieren Sie Ihre benutzerdefinierten Bindungen in der App_Start/NinjectWebCommon.cs/RegisterServices-Methode
  4. InjectPageModule hinzufügen und in NinjectWebCommon registrieren
  5. Verwenden Sie die Attributinjektion auf Ihren Seiten

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

    } 

Standard

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

Modelle

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";
    }
}

Ergebnisse aus dem Ausgabefenster

I am a model 1
From master: I am a model 1
11
Adam Bell

Ich denke, hier sind die Schritte zum Implementieren von Ninject.Web in ASP.NET-Web Forms.

  1. Implementieren Sie NinjectHttpApplication bei Global.asax. Übergeben Sie es für den Kernel, indem Sie NinjectModule implementieren.
  2. Implementieren Sie Ninject.Web.PageBase für jedes Ladeereignis der Webformularseite bei hinterem Code. Fügen Sie mit dem [Inject] -Filter eine Instanzklasse hinzu.

Für detailliertere Beispiele finden Sie unten einige nützliche Links, die ich gefunden habe:

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

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

8
nellbryant

Schauen Sie sich die Ninject.Web-Erweiterung an. Sie stellt die Basisinfrastruktur bereit https://github.com/ninject/ninject.web

4
Remo Gloor
public IGoalsService_CRUD _context { get; set; }

Das _context-Objekt wird irgendwie auf null gesetzt. Nachfolgend sind die restlichen Einstellungen aufgeführt

public partial class CreateGoal : Page
{
    [Inject]
    public IGoalsService_CRUD _context { get; set; }
}

Für globale Datei

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

Überprüfen Sie das Buch "Pro ASP.NET MVC 2 Framework, 2nd Edition" von Steve Sanderson (Apress). Der Autor verwendet Ninject, um sich mit einer Datenbank zu verbinden. Ich denke, Sie können die Beispiele verwenden und sie an Ihre Bedürfnisse anpassen.

0
jmpcm