2016-07-23 24 views
0

Ich mag ioc. Früher verwende ich Spring in Java, jetzt möchte ich DI in C# verwenden. Ich fand castle.windsor. Aber es scheint keine Injektionsklasse zu geben.Kann ich Komponente ohne Schnittstelle einspeisen Windsor

Jetzt versuche ich das, aber scheitern .... Jemand, können Sie mir helfen, es zu beheben? Oder, sag mir, welches DI-Framework kann ich verwenden?

Program.cs

using System; 
using Castle.MicroKernel.Registration; 
using Castle.MicroKernel.SubSystems.Configuration; 
using Castle.Windsor; 

namespace InjectionConsole 
{ 
    class Program 
    { 
     static void Main(string[] args) 
     { 
      var container = new WindsorContainer(); 
      container.Install(new MainInstaller()); 

      var service1 = container.Resolve<Service1>(); 

      service1.Say(); 

      // clean up, application exits 
      container.Dispose(); 

      Console.ReadKey(); 
     } 
    } 

    class MainInstaller : IWindsorInstaller 
    { 
     public void Install(IWindsorContainer container, IConfigurationStore store) 
     { 
      container.Register(Classes.FromThisAssembly()); 
     } 
    } 
} 

Service1.cs

using System; 

namespace InjectionConsole 
{ 
    class Service1 
    { 
     private Service2 Service2 { get; set; } 

     public void Say() 
     { 
      Console.WriteLine("Hello, I m Service 1, let me call Service 2"); 

      Service2.Say(); 
     } 
    } 
} 

Service2.cs

using System; 

namespace InjectionConsole 
{ 
    class Service2 
    { 
     public void Say() 
     { 
      Console.WriteLine("Hello, I m Service 2"); 
     } 
    } 
} 
+0

Der Hauptpunkt von "Inversion der Kontrolle" ist das Invertieren der Abhängigkeiten, so dass die abhängige Klasse von einer Schnittstelle eines Dienstes und nicht von der tatsächlichen Implementierung abhängt. Wenn Sie keine Schnittstellen verwenden, eliminieren Sie den Hauptvorteil von IOC-Containern und dem erwähnten Muster. –

Antwort

0

Meine Antwort ist ähnlich zu einem anderen, aber mit einem spitzfindigen Unterschied:

public class Service1 
{ 
    private readonly Service2 _service2; 

    public Service1(Service2 service2) { 
     _service2 = service2; 
    } 

    public void Say() 
    { 
     Console.WriteLine("Hello, I m Service 1, let me call Service 2"); 

     _service2.Say(); 
    } 
} 

Zuerst wird die Klasse selbst würde genau, ob die gleiche Art und Weise geschrieben werden Du benutzt einen Container wie Windsor. Die Klasse muss ihre Abhängigkeit (eine Instanz von Service2) von irgendwo "bekommen". Also setzen wir es in den Konstruktor. Service1 erwartet, was auch immer es erzeugt, um eine Service2 zu liefern. Da Sie den Container verwenden, erstellt der Container Service1. Er sieht im Konstruktor, dass er Service2 benötigt, und liefert diesen.

machen _service2 ein readonly Feld betont, dass, sobald es erstellt wird (der Konstruktor ausgeführt wird getan) Service1 hat keine weitere Kontrolle über den Wert von _service2. Es ist eingestellt und kann nicht geändert werden, nicht einmal innerhalb Service1. Das ist wichtig, weil wir Service1 zu Kontrolle diese Abhängigkeit nicht wollen. Wir wollen es erfordern diese Abhängigkeit. Es nimmt nur den Wert, der übergeben wird und verwendet es.

Auch dies ist ein haarsträubender Unterschied. Wenn Sie nicht machen _service2readonly Sie wahrscheinlich würden Sie es sowieso nicht ändern. Aber das macht deutlich, dass Sie nicht ändern können.

+0

Vielen Dank für Ihre Antwort. Ich stimme dir zu. Aber Fehler Grund ist "Eine nicht behandelte Ausnahme des Typs 'Castle.MicroKernel.ComponentNotFoundException' aufgetreten in Castle.Windsor.dll " – JonasGao

+0

Welche Komponente ist nicht registriert? –

1

Ich nehme an, Sie lösen wollen Service2 in Ihrem Dienste1 Instanz. Sie können, dass die Injektion von Konstruktor erreichen

using System; 

namespace InjectionConsole 
{ 
    class Service1 
    { 
     public Service1(Service2 s2) { 
      this.Service2 = s2; 
     } 

     private Service2 Service2 { get; set; } 

     public void Say() 
     { 
      Console.WriteLine("Hello, I m Service 1, let me call Service 2"); 

      Service2.Say(); 
     } 
    } 
} 
+0

Vielen Dank für Ihre Antwort. Aber Fehler Grund ist "Eine nicht behandelte Ausnahme des Typs 'Castle.MicroKernel.ComponentNotFoundException' aufgetreten in Castle.Windsor.dll". – JonasGao

1

Es scheint, dass Sie die Klassen Service1 und Service2 nicht als public markiert haben, was sie standardmäßig intern macht. Die Methode Classes.FromThisAssembly() lädt nur öffentliche Typen, es sei denn, Sie geben explizit an, dass sie auch nichtöffentliche Typen laden (was übrigens nicht erwünscht ist!). Überprüfen Sie the docs auf der Burg Windsor GitHub Dokumentseite.