2016-04-01 16 views
0

Wenn ich die Fabrik Muster richtig verstanden habe, könnte ich eine Fabrik haben meine Repos für die Erstellung, die eine Schnittstelle wie diese implementiert ...IoC und die Fabrik Muster

public interface IRepoFactory 
{ 
    T Get<T>() where T : IRepo 
} 

Und in dieser Fabrik ein Aufruf an RepoFactory.Get<IRepo1>() wird Gibt eine neu geprägte Instanz einer Klasse zurück, die IRepo1 implementiert.

in der Definition von RepoFactory So werde ich eine neue Instanz des entsprechenden Typs erstellen ...

switch(...) 
{ 
    case typeof(IRepo1): 
    return new Repo1();   
} 

Oder ich nehme an, ich kann einen Konstruktor für Repofactory definieren, die als Parameter nimmt, ein Schnittstelle alle möglichen Rückgabetypen repräsentieren ...

public RepoFactory(IRepo1 repo1, IRepo2 repo2, ..., IRepoN repoN) : IRepoFactory 

und mein IoC-Container, die Arbeit zu schaffen, um die Klassen tun.

Also, zu meiner Frage. Wenn ich tun einen Konstruktor wie oben erstellen, bedeutet das nicht, dass jedes Mal, wenn ich IRepoFactory als Konstruktor-Parameter ich eine neue Instanz von Repo1, Repo2, ..., RepoN? Ist das ein ressourcenintensiver Prozess? Ist es eine verschwenderische Art, Dinge zu tun, wenn ich im gegebenen Fall wahrscheinlich nur einen Teil der Gesamtzahl der verfügbaren Repos benötige?

Gibt es eine Möglichkeit, den IoC (Unity, in meinem Fall) nur eine Instanz zu dem Zeitpunkt zu erstellen, wenn es benötigt wird, ein Lazy Loading, wenn Sie so wollen? Oder mache ich mir einfach Sorgen um nichts?

+1

Ich habe nicht Unity verwendet, aber Autofac und StructureMap können beide Objektfabriken aus der Box injizieren. Machen Sie den Konstruktorparameter einfach zu einer Funktion, z. B. MyClass (Func > RepoFactory). Dann können Sie in der Klasse, die die Abhängigkeit übernimmt, var repo = repoFactory() sagen, und Sie erhalten eine neue Instanz. Unity kann eine ähnliche Funktion haben. – Nelson

+0

Ich werde noch einmal durch die Dokumentation wühlen, @Nelson, Ta. –

Antwort

1

Sie mißverstanden Factory. Factory sollte Instanzen erstellen. Das heißt, im Factory-Konstruktor sollte nichts neben Di-Container oder LifeTimeScope sein.

Sie können Ihre eigene Fabrik verwenden oder Sie können automatisch generierte Fabrik verwenden.

Ich bin nicht vertraut Einheit, aber ich überprüfte sie haben.

public class MyService : IMyService 
    { 
     private readonly Func<IRepo1> _repo1; 

     public MyService(Func<IRepo1> repo1) 
     { 
      _repo1 = repo1; 
     } 

     public void Method1() 
     { 

      var myRepo = _repo1(); 
     } 

     public void Method2() 
     { 
      //Repo1 instance will be different than in Method1 
      var myRepo = _repo1(); 
     } 
    } 
1

Wenn Sie einen Container haben, können Sie den Container bei Bedarf den Repo-Typ auflösen lassen.

Hier ist ein grobes Beispiel, wie Sie es tun können. Beachten Sie, dass Sie den Code so ändern, dass er zu Ihrem spezifischen Container passt, und auch hier ist die Annahme, dass Sie den Container bereits so konfiguriert haben, dass er weiß, dass er die gewünschten Typen auflösen kann.

public class DefaultRepoFactory : IRepoFactory { 
    IUnityContainer container; 

    public DefaultRepoFactory(IUnityContainer container) { 
     this.container = container; 
    } 

    public T Get<T>() where T : IRepo {   
     return (T)container.Resolve<T>(); 
    } 
} 

Konfiguration

IUnityContainer myContainer = new UnityContainer(); 
IRepoFactory myDefaultFactory = new DefaultRepoFactory(myContainer); 
myContainer.RegisterInstance<IRepoFactory>(myDefaultFactory); 
+0

Ist es nicht besser, wenn wir eine generische Klasse anstelle einer generischen Methode verwenden und generische Factory registrieren. Weil wir jetzt in unserem Service 'IRepoFactory' haben, aber wir wissen nicht, welche Repositories verwendet werden.Wenn wir es in eine generische Klasse ändern, wird es so aussehen: 'MyService (IRepoFactory repo1)' –

+0

Es würde funktionieren, aber ich würde argumentieren, dass eine Abhängigkeit von IUnityContainer keine gute Wahl wäre. – AksharRoop