2012-04-03 10 views
7

Ich habe die folgende SchnittstelleMapping zwischen T -> IHandler <T>

public interface IHandler<T> 
{ 
    void Handle(T myObject); 
} 

Ich möchte eine HandlersManager Klasse haben, mit einer Abbildung zwischen Objekttypen mit ihren entsprechenden Handler hält, aber ich bin nicht sicher, wie ich das Objekt definieren soll, das dieses Mapping enthält.

Zum Beispiel, was ich möchte ist, dass wir dieses:

typeof(string) --> instance of IHandler<string> 
typeof(MyClass) --> instance of IHandler<MyClass> 

Das Beste, was ich so weit gekommen war Dictionary<Type, object> für die Zuordnung zu definieren, aber in diesem Fall würde ich den Wert werfen zu IHandler<T> jedes Mal, wenn ich es bekomme.

Gibt es eine bessere Lösung oder etwas, das ich komplett verpasst habe?

+1

Wenn 'IHandler ' 'IHandler' geerbt hat, dann könnten Sie ein Wörterbuch von' 'viel wie passiert mit' IEnumerable' – Jodrell

+2

@Jodrell Da 'IHandler' wäre eine leere Schnittstelle, dies ist das gleiche wie mit 'Objekt', da die Besetzung noch benötigt wird. –

Antwort

5

Das ist so gut wie es nur mit einer generischen IHandler<T> Schnittstelle möglich ist.

Um mehr Möglichkeiten zu erkunden, könnten wir eine nicht-generische Version der Schnittstelle definieren:

public interface IHandler 
{ 
    void Handler(object myObject); 
} 

Dann könnte man auch eine generische abstrakte Basisklasse definieren, die sowohl IHandler<T> implementiert und IHandler:

public abstract class BaseHandler<T> : IHandler, IHandler<T> 
{ 
    public abstract void Handle(T myObject); 

    void IHandler.Handle(object myObject) 
    { 
     ((IHandler<T>)this).Handle((T) myObject); 
    } 
} 

an dieser Stelle können Sie ein IDictionary<Type, IHandler> und Sie direkt IHandler.Handle auf den Werten aufrufen können Sie daraus ziehen:

var obj = /* whatever */ 
dictionary[obj.GetType()].Handle(obj); 

Auf der anderen Seite haben wir jetzt eine zusätzliche Schnittstelle und eine abstrakte Basisklasse, nur um eine Umwandlung von "Benutzer" -Code zu verbergen, was sich nicht sehr beeindruckend anhört.

10

Ich vermute, dass Sie dies verwenden, um Abhängigkeiten aufzulösen. Verwenden Sie stattdessen einen dedizierten Container, der diese Probleme für Sie behandelt.

Wenn Sie nicht das tun wollen, wollen Sie etwas wie folgt aus:

Dictionary<Type, object> dictionary; 

IHandler<T> Resolve<T>() { 
    return (IHandler<T>)dictionary[typeof(T)]; 
} 

Es gibt keine andere Art und Weise mit Generika.

Gibt es eine bessere Lösung oder etwas, das ich komplett verpasst habe?

Nein, aber Manager Klassen sind in der Regel Code Gerüche. Achtung.

+0

Es klingt eher nach einer Fabrikklasse als nach einer unspezifischen Managerklasse, also glaube ich nicht, dass hier ein Geruch ist. – Rup

+1

@Rup: Ehrlich gesagt, keiner von uns kennt die Verwendung, ohne den Kontext zu sehen. Er nannte es einen Manager, und es sieht aus wie ein Resolver. Das ist ein Geruch, denn wenn ich eine Klasse habe, die diesen Manager benutzt, weiß ich nicht, dass es konkrete'IHandler 's Auflösung ist, und deshalb weiß ich nicht, was'IHandler 's es abhängig ist. – jason

Verwandte Themen