2016-12-28 4 views
1

Ich habe ein Wörterbuch - der Schlüssel davon ist System.Type. Ich beschränke die Wörterbucheinträge nicht weiter; Das Wörterbuch wird jedoch nur über eine öffentliche Klassenschnittstelle verfügbar gemacht. Ich imitierte ein Ereignissystem.Constraining System.Type Als generischer Parameter für Typ Sicherheit

Die System.Collections.GenericDictionary sieht aus wie:

private Dictionary<Type, HashSet<Func<T>>> _eventResponseMap; 

Eine der Methoden, die das Wörterbuch aussetzt hat die folgende Signatur:

public bool RegisterEventResponse<T>(Type eventType, Func<T> function) 

aber ich will nicht die Klasse Benutzer in der Lage sein, über diese Signatur ein beliebiges System.Type zum Wörterbuch hinzuzufügen. Gibt es eine Möglichkeit, den Parameter Type weiter einzuschränken?

Was ich wirklich will, ist so etwas wie (Pseudo-Code):

public bool RegisterEventResponse<T>(Type eventType, Func<T> function) where Type : ICustomEventType 
+0

Es gibt wahrscheinlich etwas Müll im obigen Code. Wenn du darüber hinwegsehen könntest, wäre das großartig. Ich fotografiere hier im Dunkeln, konzeptionell (wird per Vorschlag geändert) – Thomas

+1

Anstelle von 'Type' können Sie einen anderen generischen Typ wie' T2' verwenden und diesen auf bestimmte Typen beschränken. [Dies wurde bereits hier beantwortet] (http://stackoverflow.com/a/4834066/4767498) mit Richtlinienmuster. Dieser Ansatz führt zu einem Kompilierzeitfehler, wenn der richtige Typ nicht verwendet wird. Einfacher wäre es, Typen zur Laufzeit zu prüfen. –

Antwort

2

Warum die Signatur Ihrer Methode nicht ändern?

public bool RegisterEventResponse<TEvent, TReturn>(Func<TReturn> function) 
    where TEvent: ICustomEventType 
{ 
    _eventResponseMap[typeof(TEvent)] = function; 
} 

Ja, Sie verlieren Inferenz, aber Sie erhalten Typ Sicherheit. Anstatt RegisterEventResponse(typeof(CustomEvent),() => 1) zu schreiben, müssten Sie RegisterEventResponse<CustomEvent, int>(() => 1) schreiben.

+0

Das mag ich. Wie würde ein Aufruf grob aussehen (mit welchen Müllarten soll man demonstrieren)? – Thomas

+2

Beachten Sie, dass das, was ich meinte, indem Sie einen Parameter hinzufügen :) – BradleyDotNET

+0

@BradleyDotNET stört es Sie, wenn ich das akzeptiere (per eine Antwort auf meine obigen Kommentar)? Dies ist ein sehr explizites Beispiel dafür, was wie das aussieht, was ich brauche. Viel lernen, hier. – Thomas

3

Nein, Sie erhalten keine Zeit Sicherheit auf Type kompilieren.

könnten Sie zwingen T (oder einen Parameter hinzuzufügen) zu ICustomEventType dann typeof in RegisterEventResponse verwenden für die Type Objekt, das Sie suchen zu erhalten.

Alternativ nur eine Ausnahme:

if (!typeof(ICustomEventType).IsAssignableFrom(typeof(T)) 
{ 
    throw new ArgumentException("Type is not supported"); 
} 
+0

Ich habe nicht einmal daran gedacht, in diesem Fall einen Fehler zu werfen. Es wäre schön, wenn die Kompilierzeitsicherheit erreichbar wäre (weiß nicht, ob das überhaupt machbar wäre). Ein Problem mit dem Fehlerstück ist, dass es bedeutet, dass der Benutzer mit den Implementierungsdetails vertrauter sein müsste - was kein großer Einwand ist, aber ... Sie wissen. – Thomas

+1

@Thomas Nur um Kompilierzeit Sicherheit zu erhalten, ist es, einen tatsächlichen generischen Parameter (nicht 'Type') wie in meinem mittleren Absatz zu beschränken. – BradleyDotNET

+0

@Thomas oder wenn Sie nicht viele verschiedene Typen haben, können Sie verschiedene Methodenüberladungen schreiben. Wie auch immer, dies kann zu einem DRY-Problem führen. –

Verwandte Themen