Ich habe die IRespository
zweimal (mit Namen) im folgenden Code registriert:
// Setup the Client Repository
IOC.Container.RegisterType<ClientEntities>(new InjectionConstructor());
IOC.Container.RegisterType<IRepository, GenericRepository>
("Client", new InjectionConstructor(typeof(ClientEntities)));
// Setup the Customer Repository
IOC.Container.RegisterType<CustomerEntities>(new InjectionConstructor());
IOC.Container.RegisterType<IRepository, GenericRepository>
("Customer", new InjectionConstructor(typeof(CustomerEntities)));
IOC.Container.RegisterType<IClientModel, ClientModel>();
IOC.Container.RegisterType<ICustomerModel, CustomerModel>();
Aber wenn ich dies beheben möchte (um das zu verwenden IRepository
), muss ich eine manuelle Lösung wie folgt durchführen:
public ClientModel(IUnityContainer container)
{
this.dataAccess = container.Resolve<IRepository>(Client);
.....
}
Was ich tun möchte, ist, es im Konstruktor auflösen zu lassen (genau wie IUnityContainer
). Ich brauche eine Möglichkeit zu sagen, in welchen benannten Typ ich auflösen soll.
So etwas wie das: (HINWEIS: Kein echter Code)
public ClientModel([NamedDependancy("Client")] IRepository dataAccess)
{
this.dataAccess = dataAccess;
.....
}
Gibt es eine Möglichkeit, meinen gefälschten Code zum Laufen zu bringen?
quelle
IRepository>("Customer")
sollte das in einer anderen Instanz vonClientModel
Dies ist eine sehr späte Antwort, aber die Frage wird immer noch in Google angezeigt.
Also sowieso 5 Jahre später ...
Ich habe einen ziemlich einfachen Ansatz. Wenn Sie "benannte Abhängigkeit" verwenden müssen, liegt dies normalerweise daran, dass Sie versuchen, eine Art Strategiemuster zu implementieren. In diesem Fall erstelle ich einfach eine Indirektionsebene zwischen Unity und dem Rest meines Codes, die
StrategyResolver
als nicht direkt von Unity abhängig bezeichnet wird.public class StrategyResolver : IStrategyResolver { private IUnityContainer container; public StrategyResolver(IUnityContainer unityContainer) { this.container = unityContainer; } public T Resolve<T>(string namedStrategy) { return this.container.Resolve<T>(namedStrategy); } }
Verwendung:
public class SomeClass: ISomeInterface { private IStrategyResolver strategyResolver; public SomeClass(IStrategyResolver stratResolver) { this.strategyResolver = stratResolver; } public void Process(SomeDto dto) { IActionHandler actionHanlder = this.strategyResolver.Resolve<IActionHandler>(dto.SomeProperty); actionHanlder.Handle(dto); } }
Anmeldung:
container.RegisterType<IActionHandler, ActionOne>("One"); container.RegisterType<IActionHandler, ActionTwo>("Two"); container.RegisterType<IStrategyResolver, StrategyResolver>(); container.RegisterType<ISomeInterface, SomeClass>();
Das Schöne daran ist, dass ich den StrategyResolver nie wieder berühren muss, wenn ich in Zukunft neue Strategien hinzufüge.
Es ist sehr einfach. Sehr sauber und ich habe die Abhängigkeit von Unity auf ein striktes Minimum beschränkt. Das einzige Mal, dass ich den StrategyResolver berühren müsste, wäre, wenn ich mich entscheide, die Containertechnologie zu ändern, was sehr unwahrscheinlich ist.
Hoffe das hilft!
Bearbeiten: Die akzeptierte Antwort gefällt mir nicht wirklich, da Sie bei Verwendung des
Dependency
Attributs im Konstruktor Ihres Dienstes tatsächlich eine starke Abhängigkeit von Unity haben. DasDependency
Attribut ist Teil der Unity-Bibliothek. An diesem Punkt können Sie genauso gutIUnityContainer
überall eine Abhängigkeit übergeben.Ich bevorzuge es, wenn meine Serviceklassen von Objekten abhängen, die ich vollständig besitze, anstatt überall stark von einer externen Bibliothek abhängig zu sein. Durch die Verwendung von
Dependency
Attributen werden die Konstruktorsignaturen weniger sauber und einfach.Darüber hinaus ermöglicht diese Technik das Auflösen benannter Abhängigkeiten zur Laufzeit, ohne die benannten Abhängigkeiten im Konstruktor, in der Anwendungskonfigurationsdatei oder in der Verwendung fest codieren zu müssen. Dies
InjectionParameter
sind alles Methoden, die wissen müssen, welche benannte Abhängigkeit zur Entwurfszeit verwendet werden soll.Bearbeiten (19.09.2016): Für diejenigen, die sich fragen könnten, weiß der Container, dass er sich selbst übergeben muss, wenn Sie eine
IUnityContainer
Abhängigkeit anfordern , wie in derStrategyResolver
Konstruktorsignatur gezeigt .Bearbeiten (20.10.2018): Hier ist eine andere Möglichkeit, einfach eine Factory zu verwenden:
public class SomeStrategyFactory : ISomeStrategyFactory { private IStrategy _stratA; private IStrategy _stratB; public SomeFactory(IStrategyA stratA, IStrategyB stratB) { _stratA = stratA; _stratB = stratB; } public IStrategy GetStrategy(string namedStrategy){ if (namedStrategy == "A") return _stratA; if (namedStrategy == "B") return _stratB; } } public interface IStrategy { void Execute(); } public interface IStrategyA : IStrategy {} public interface IStrategyB : IStrategy {} public class StrategyA : IStrategyA { public void Execute(){} } public class StrategyB : IStrategyB { public void Execute() {} }
Verwendung:
public class SomeClass : ISomeClass { public SomeClass(ISomeStrategyFactory strategyFactory){ IStrategy strat = strategyFactory.GetStrategy("HelloStrategy"); strat.Execute(); } }
Anmeldung:
Dieser zweite Vorschlag ist dasselbe, verwendet jedoch das werkseitige Entwurfsmuster.
Hoffe das hilft!
quelle
T
Sie einfach eine Methode habenIActionHandler ResolveMyStrategy(string strategyName).
IUnityContainer
an den Resolver-Typ zu übergeben, habe ich einFunc<string, ISomeInterface> resolver
Argument als Konstruktor verwendet. So können Sie die Auflösung an das DI-Projektmodul delegieren und somit unabhängig vom verwendeten Container sein. Registrierung :container.RegisterInstance<IStrategyResolver>(new StrategyResolver(key => container.Resolve<ISomeInteface>(key)))
. Auch dieser Ansatz ist restriktiver gegenüber einem möglichen Missbrauch von Service Locator.Sie sollten ParameterOverrides verwenden können
var repository = IOC.Container.Resolve<IRepository>("Client"); var clientModel = IOC.Container.Resolve<ClientModel>(new ParameterOverrides<ClientModel> { {"dataAccess", repository } } );
edit: Ich bin mir nicht sicher, warum Sie den UnityContainer weitergeben - persönlich fügen wir unsere Abhängigkeiten in den Konstruktor selbst ein (was nach dem, was ich gesehen habe, "normal" ist). Unabhängig davon können Sie in Ihren RegisterType- und Resolve-Methoden einen Namen angeben.
IOC.Container.RegisterType<IRepository, GenericRepository>("Client"); IOC.Container.Resolve<IRepository>("Client");
und es gibt Ihnen den Typ, den Sie für diesen Namen registriert haben.
quelle
Tun Sie dies nicht - erstellen Sie einfach ein
class ClientRepository : GenericRepository { }
und verwenden Sie das Type-System.quelle