2017-10-15 5 views
3

Ich arbeite daran, EF einfacher zum Komponententest zu machen, indem ich einige Helfer schreibe, die Eigenschaften für mich machen. Ich habe ein paar Play FelderTyp mit einem generischen Rückgabetyp einschalten

private Mock<DbSet<Workflow>> mockedWorkFlows; 
private Mock<DbSet<WorkflowError>> mockedWorkFlowErrors; 

Und ich möchte eine generische Funktion mich das richtige Trägerfeld zurückkehren zu können, mit der folgenden Funktion

public Mock<DbSet<T>> Mocked<T>(T t) where T : class 
{ 
    if ((object)t is Workflow) 
    { 
     return mockedWorkFlows; //cannot Workflow to T 
    } 
} 

Es gibt mehrere private Träger Felder, die ich will basierend auf dem übergebenen Typ zurückgegeben werden.

Allerdings, auch wenn ich eine Klassenbeschränkung von Workflow hinzufügen, bekomme ich den gleichen Fehler.

Ich habe auch versucht t's Typ zu schalten, aber kein Glück gibt es auch nicht. Die Typen der verschiedenen unterstützenden Felder haben keinen gemeinsamen Vorfahren, außer Objekt. Ist das, was ich versuche, möglich?

+0

Ich sehe nicht, was der Sinn dieser Methode wäre. Das Erstellen eines Mocks dauert 1 Zeile Code und wenn Sie den Mock einrichten möchten, müssen Sie jeden Mock trotzdem individuell einrichten, also warum erstellen Sie nicht einfach eine Factory für Mocks bestimmter Typen. – FCin

+0

Es ist mehr als eine Codezeile, um ein IDbSet aus Ihrem EF-Kontext zu verspotten. Ich habe eine fließende Schnittstelle für die Zuordnung der Daten, aber Sie müssen das Hintergrundfeld irgendwo offenlegen, denn wenn Sie es ausspionieren, wird das tatsächlich aufgerufen. Ich möchte nur eine kleinere API, anstatt einen WorkflowSMocked, WorkflowErrorsMocked usw. für alle IDbSet-Eigenschaften des Kontextes. – wootscootinboogie

+0

Anstatt sich über das 'DbSet' lustig zu machen, haben Sie sich überlegt, stattdessen die' SqlConnection' zu verspotten, zum Beispiel mit dem Effort Framework? https://github.com/tamasflasich/effort –

Antwort

6

Wenn ich Ihre Absicht richtig verstehen - Sie können es wie folgt tun:

// no need to pass instance of T - why? 
public Mock<DbSet<T>> Mocked<T>() where T : class 
{ 
    if (typeof(T) == typeof(Workflow)) { 
     // first cast to object, then to return type to avoid compile error 
     // compiler does not know mockedWorkFlows is Mock<DbSet<T>>, but you 
     // know it already, because you checked type 'T' 
     return (Mock<DbSet<T>>) (object) mockedWorkFlows; //cannot Workflow to T 
    } 
    // etc 
    return null; 
} 

Ob es eine gute Idee ist oder nicht, ist eine andere Geschichte.

+0

das ist, was ich gesucht habe. Ich habe versucht, die Einfachheit des Einschalttyps für C# 7 zu verwenden, aber das ist letztendlich das, wonach ich gesucht habe (obwohl ich jetzt einen anderen Fehler bekomme! :)) – wootscootinboogie

1

Es ist möglich, ernsthaft switch C# 7s zu missbrauchen zu erreichen, was Sie auf einem nicht verwandten Wert durch Umschalten wollen und mit dem var Muster mit when Wachen:

public Mock<DbSet<T>> Mocked<T>() where T : class 
{ 
    switch(true) 
    { 
     case var _ when typeof(T) == typeof(Workflow): 
      return ... 
     case var _ when typeof(T) == typeof(WorkflowError): 
      return ... 
     default: 
      return null; 
    } 
} 

Aber es ist wirklich schrecklich Code, don so wenden Sie sich bitte tu das nicht!

In der Lage, auf Typen in switch Aussagen übereinstimmen ist eine sehr häufige Anfrage. Es gibt Vorschläge für Verbesserungen von C# im offiziellen Sprachrepos auf Github (siehe Proposal: switch on System.Type und p Proposal: Pattern match via generic constraint). Wenn zu C# (currently, set for "a 7.X release") mehr Musterübereinstimmungsfunktionalität hinzugefügt wird, können wir eine bessere Syntax für diese Funktionalität erhalten.

Verwandte Themen