2009-05-13 9 views
2

Ich entwarfe derzeit eine Klassenbibliothek, die Daten an eine Web Application Graph Rendering Engine in C# liefert. Ich definiere derzeit die Schnittstellen dieser Bibliothek.Interface Design mit C# Generics

Ich habe eine IGraphData-Schnittstelle, die ich mit einem Dienst zwischenspeichern möchte, der auf den Cache zugreift, dies heißt IGraphDataCacheService und hat Methoden zum Hinzufügen und Abrufen von IGraphData-Objekten zum und vom Cache festgelegt und abgerufen. Der Cache-Dienst wird ein Singleton sein.

Ich bin verwirrt über den richtigen Weg, dies zu implementieren, so dass es nur eine Cache-Service ist die generischen IgraphData Objekte erhalten und festlegen kann.

kam ich mit auf den Punkt:

interface IGraphDataCacheService { 

IGraphData<object> Get(string identifier); 
void Set(IGraphData<object> graphData);} 

oder dies:

T Get<T, P>(string identifier) where T : IGraphData<P>; 
void Set<T,P>(T graphData) where T : IGraphData<P>; 

Kann jeder ein Angebot jede Beratung helfen?

Dank

Antwort

8

Warum machen Sie nicht einfach die Schnittstelle generisch?

interface ICacheService<T> { 
    T Get(string identifier); 
    void Set(T graphData); 
} 

, wenn Sie möchten, können Sie typ beschränken T vom Typ sein IGraphData, oder man könnte es schreiben, wie:

interface IGraphDataCacheService<T> { 
    IGraphData<T> Get(string identifier); 
    void Set(IGraphData<T> graphData); 
} 
3

Einige Punkte:

  1. Ich würde wahrscheinlich die Interface-Methoden umbenennen mehr Signet einer Caching-Dienst zu sein. Zum Beispiel Fetch und Store anstelle von Get und Set, was es so klingen lässt, als würden Sie den Provider erhalten oder einstellen, anstatt die Daten zwischenzuspeichern.

  2. Sicherstellen, dass es nur ein Cache ist eine Implementierung Detail, keine Schnittstelle ein.

ein Singleton zu implementieren, versuchen so etwas wie:

public class SingletonCacheService : IGraphDataCacheService { 
    private static Singleton instance; 

    private Singleton() {} 

    // snip implementation of IGraphDataCacheService methods ... 

    public static Singleton Instance { 
     get { 
     if (instance == null) { 
      instance = new Singleton(); 
     } 
     return instance; 
     } 
    } 
} 

Beachten Sie, dass diese einfache Version ist nicht thread.

+0

Siehe unten, wie dies mit einem statischen Initialisierer stattdessen zu erreichen. –

1

Beide Alternativen scheinen auf einen Blick plausibel; Meine Vermutung ist, dass Sie einen "typischen" Client-Code schreiben müssen, um zu entscheiden. z.B. Ist der typische Kunde ‚wissen‘ die Art der Daten mit der Kennung zugeordnet ist es aufzuzublicken? Ein guter API-Entwurf erfordert die Identifizierung der wichtigsten Anwendungsszenarien und deren Verwendung als Information für das Design.

0

Sie können nicht sicherstellen, dass nur eine einzige Instanz eine Schnittstelle implementiert. Sie können jedoch eine Klasse (z. B. GraphDataCacheServiceImpl) erstellen, die die Schnittstelle ein Singleton implementiert, indem Sie sie versiegeln und nur eine Getter-Eigenschaft bereitstellen, wobei das Objekt als statische Variable von einem privaten Konstruktor erstellt wird. Siehe unten. Soweit es Generika, ist es nicht genau klar, was Sie erreichen wollen. Aber ich würde vermuten, dass das Folgende nahe ist, was Sie wollen.

interface IGraphDataCacheService<T> { 

IGraphData<T> Get(string identifier); 
void Set(IGraphData<T> graphData); 

} 


public sealed class GraphDataCacheServiceImpl<T> : IGraphDataCacheService<T> 
{ 

    private GraphDataCacheServiceImpl() 
    { 
     // .. 
    } 

    static GraphDataCacheServiceImpl() 
    { 
    Instance = new GraphDataCacheServiceImpl<T>(); 
    } 

    public IGraphData<T> Get(string id) 
    { 
     return new GraphDataImpl<T>(); 
    } 

    public void Set(IGraphData<T> graphData) 
    { 
    } 

    public static GraphDataCacheServiceImpl<T> Instance {get; private set;} 
} 
1

Wenn ich Ihre Frage richtig verstanden werden wollen Sie die generische behandeln Typen wie sie sind die gleichen, aber in der aktuellen .NET-Implementierung können Sie dies nicht tun.

IGraphData <String> kann nicht als IGraphData < > Objekt übergeben werden, sie sind tatsächlich verschiedene Arten obwohl String ist ein Objekt, die generische Typen sind nicht verwandt und nicht gegossen oder weitergegeben werden, wie sie die gleichen sind .

Wenn Sie die IGraphData-Schnittstelle steuern, können Sie eine IGraphData-Schnittstelle erstellen und IGraphData daraus ableiten und IGraphData verwenden, um auf den Cache zuzugreifen. Es hängt nur davon ab, wie Sie es benutzen und wofür Sie die Kontrolle haben.

Sie können tun, was Sie in C# 4.0 wollen. Es gibt einen Artikel darüber here