10 Stimmen

Konstruktorinjektion mit anderen, nicht abhängigen Konstruktorargumenten

Ich bin neu bei IOC-Containern und fange gerade mit NInject an.

Was tun Sie, wenn Ihr Konstruktor Parameter haben soll, die keine Dienste sind und nicht vom IOC-Container instanziiert werden müssen?

Zum Beispiel:

public class Person
{
    private readonly string _name;
    private readonly IPersonRepository _repository;

    public Person(string name, IPersonRepository repository)
    {
        _name = name;
        _repository = repository;
    }

    ......
}

Stellen Sie sich das vor Name ist eine Anforderung der Klasse Person. Um also sicherzustellen, dass eine Person immer einen Namen hat, muss dieser an den Konstruktor übergeben werden.

Wie würden wir eine Instanz von Person mit NInject erhalten? Der Name muss von dem Teil der Anwendung übergeben werden, der eine neue Person erstellt, während der IOC-Container das IPersonRepository übergeben muss.

Ich verstehe, dass entweder der Name oder das Repository stattdessen mit einer Eigenschaft injiziert werden könnte, aber das wäre keine saubere Lösung - wir verlieren etwas von der semantischen Kraft der Programmiersprache.

8voto

cbp Punkte 24483

Es ist mehr als ein Jahr her, dass ich diese Frage gestellt habe, und ich weiß jetzt mehr als damals. Kevins Antwort ist richtig und die beste Praxis, aber manchmal muss man mit Legacy-Klassen arbeiten und möchte etwas tun, was ich in meiner Frage beschrieben habe. Hier ist, wie ich es mit NInject tun:

public class Person
{
    [Inject]
    public IPersonRepository PersonRepository { get; set; }

    private string _name;

    public Person(string name)
    {
         _name = name;
         StaticKernelContainer.Inject(this);
    }
}

Eine Implementierung von StaticKernelContainer findet sich im Projekt NInject Web extensions.

5voto

Kevin McMahon Punkte 2634

Die Klasse, wie oben geschrieben, wäre kein guter Kandidat für die Verwendung mit einem IOC-Container. Sie vermischen hier Bedenken mit der Entität Person, die einen Zustand (den Namen) hält und eine Aktion durchführt (wofür auch immer das Repository verwendet wird). Wenn Sie Ihren Code so umgestalten, dass die Person-Entität über eine Klasse abgerufen oder erstellt wird, die eine Implementierung des IPersonRepository über den Konstruktor übernimmt, dann sind Sie an einem Punkt, an dem die Dependency Injection mehr Sinn macht.

2voto

Charlie Flowers Punkte 17000

Ich stimme Kevin McMahons obiger Antwort nicht zu, und der Grund dafür ist, dass ich Code für Dependency Injection gesehen habe, der genau das tut, was Sie wollen ... nur mit einem anderen IoC-Container. Und zwar war es Castle Windsor, ein anderer IoC-Container. Es würde Ihnen erlauben, einen Abschnitt in Ihrer Konfigurationsdatei zu erstellen, um zu sagen, welche Werte für name bereitgestellt werden sollen (es macht nicht viel Sinn, dies für name zu tun, aber wenn es eine Eigenschaft wie "connectionString" wäre, könnte es viel Sinn machen).

Also ... es ist nicht so, dass das, was Sie versuchen zu tun, nicht für Dependency Injection im Allgemeinen geeignet ist ... es ist nur so, dass Ninject sich damit nicht wohl zu fühlen scheint (oder vielleicht kann Ninject es auch unterbringen ... Ich kenne nicht alle seine weniger genutzten Funktionen gut genug, um das zu sagen).

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X