2010-12-30 3 views
0

Ich versuche, eine Singleton-Klasse wie unten zu erstellen, wo MyRepository in separaten DAL-Projekt liegt. Es verursacht mir ein zirkuläres Referenzproblem, weil die GetMySingleTon() Methode MySingleTon Klasse zurückgibt und ihren Zugriff benötigt. Genau wie ich brauche MyRepository Zugriff im Konstruktor der MySingleTon Klasse.Circular Referenz Problem Singleton

public class MySingleTon 
    { 
    static MySingleTon() 
    { 
     if (Instance == null) 
     { 
     MyRepository rep = new MyRepository(); 
     Instance = rep.GetMySingleTon(); 
     } 
    } 
    public static MySingleTon Instance { get; private set; } 
    public string prop1 { get; set; } 
    public string prop2 { get; set; } 
    } 

UPDATE: ich es sehr zu Unrecht tat. Ich denke, brauchte kein Singleton. Jetzt habe ich eine Klasse mit statischen Eigenschaften in einem dritten Projekt erstellt und ich setze es einmal und überall darauf zugreifen. Und es hat mein Problem für jetzt gelöst.

Vielen Dank für Ihre Antworten.

+0

Was genau macht MyRepository? Es klingt, als wäre es verantwortlich für die Rückgabe der MySingleton-Instanz. Wenn ja, können Sie den Initialisierer nicht durch einen Konstruktor oder eine statische Methode ersetzen und "this" übergeben, anstatt ein neues Repository in MySingleton zu erstellen? –

+0

Warum machst du es so? – jason

Antwort

1

Das Repository sollte ein Singleton-Objekt nicht zurück, ein Repository verwendet wird, auf Daten zuzugreifen und nicht Singleton Objekte zurück. Ihr Repository könnte an sich ein Singleton sein, aber ich empfehle es nicht, und ich empfehle auch nicht, ein Singleton für die Klasse zu verwenden, die das Repository verwendet. In dem Code, den Sie haben, scheint es, als müsste das Repository die "Business-Schicht" kennen, die alle durcheinander ist, die Beziehungen sollten nur in eine Richtung gehen. Ich würde es wie schreiben:

public class MySingleTon 
{ 
    private MySingleTon() 
    { 
     // You constructor logic, maybe create a reference 
     // to your repository if you need it 
    } 

    private static MySingleTon _instance; 
    public static MySingleTon Instance { 
     get 
     { 
      if(_instance == null) 
      _instance = new MySingleTon(); 
      return _instance; 
     } 
    } 
    public string prop1 { get; set; } 
    public string prop2 { get; set; } 
} 

Ich empfehle meine Lösung nicht, aber es sollte Sie Problem lösen. Was ich empfehle, ist in die Abhängigkeitsinjektion und Inversion der Kontrolle zu schauen, da Ihr Design irgendwie falsch scheint. Schauen Sie sich NInject an.

EDIT: Eine andere Sache, warum hat Ihr Singleton mehrere Eigenschaften, die öffentlich sind? Ein Singleton sollte keine Eigenschaften offenlegen, die nur Funktionen offenlegen sollten, und sollte hauptsächlich verwendet werden, wenn Sie eine Utility-Klasse wie Math oder einen echten Singleton wie einen Logger haben.

0

Obwohl es nicht gut ist, eine solche Klassenintraktion zu erstellen und ich weiß nicht, was der Grund dafür ist.

aber Sie können

Erstellen Sie ein Projekt namens öffentliche Schnittstelle und definieren eine Schnittstelle IMyRepository mit den öffentlichen Funktionen auf den folgenden Code ähnlich tun, die Sie von MyRepository Klasse verfügbar machen möchten.

Erstellen Sie eine öffentliche Eigenschaft in der Singleton-Klasse, die IMyRepository zurückgibt und auch außerhalb der Baugruppe gesetzt werden kann.

Jetzt müssen Sie diese Eigenschaft explizit aus den Assemblys festlegen, die auf Ihre Singelton-Assembly verweisen, und ich nehme an, dass Sie das Objekt der MyRepository-Klasse aus anderen Assemblys erstellen können.

Bitte beachten Sie: Die obige Lösung ist nur ein Trick, um die Zirkelreferenz nicht die optimale Lösung zu brechen.

0

Während die Singleton-Accessor-Eigenschaft in der Klasse selbst eine allgemein verwendete Abkürzung ist, kann es in komplizierteren Situationen, in denen Sie mit Instanzen mehrerer verwandter Klassen arbeiten müssen, die falsche Methode sein. Das Problem besteht darin, Bedenken innerhalb einer einzigen Klasse zu vermischen.

Ihre MySingleton Klasse sollte eher etwas MyClass sein, das im Allgemeinen unabhängig von der Anzahl der Instanzen implementiert wird, die zur Laufzeit vorhanden sind. Ebenso muss MyRepository in der Lage sein, eine beliebige Anzahl von MyClass Instanzen zu verwalten und bereitzustellen. Die Tatsache, dass es sich nur um eine Singleton-Instanz von MyClass handelt, kann in eine separate Factory-Klasse (oder Accessor oder wie auch immer Sie es nennen) gekapselt werden, die MyClass und MyRepository zusammen bindet.

Also versuchen Sie Ihr Design in der folgenden Art und Weise (schematisch) zu überdenken:

public class MyClass { ... } 

public class MyRepository 
{ 
    public MyClass GetMyClassInstance(...); 
} 

public static class MyClassFactory 
{ 
    public static MyClass SingletonInstance 
    { 
     get 
     { 
      if (singletonInstance == null) 
       singletonInstance = myRepository.GetMyClassInstance(...); 
      return singletonInstance; 
     } 
    } 
} 

Die verbleibende Frage ist, wo sich myRepository kommen. Zum Beispiel kann es beim Programmstart erstellt und in MyclassFactory als Mitglied Feld bereitgestellt werden.

Am Ende des Tages kann vieles vereinfacht werden, wenn Sie eine Inversion des Kontrollcontainers in Betracht ziehen. Der nächste Schritt ist auch der Übergang zu einem schnittstellenbasierten Design. Dies gibt Ihnen eine weitere Abstraktionsebene und bietet mehr Flexibilität hinsichtlich der Austauschbarkeit von Implementierungen.

0

zusätzlich zu dem Code von Saurabh, werden Sie die Singleton Klasse ändern:

public class MySingleTon 
    { 
    static MySingleTon() 
    { 
     if (Instance == null) 
     { 
     Instance = new MySingleTon(); 
     } 
    } 

    private MySingleTon(){} 

    public static MySingleTon Instance { get; private set; } 
    public IMyRepository MyRepository{ get; set ;} 

    }