2017-07-18 6 views
0

Ich habe das nächste Szenario:Casting Generisches Typ Basistyp

public class RequestBase { } 
public class ResponseBase { } 

public interface IService<TRequest, TResponse> 
      where TRequest : RequestBase where TResponse : ResponseBase 
{ 
    TResponse Execute(TRequest request); 
} 

public class MyRequest : RequestBase { } 
public class MyResponse : ResponseBase { } 

public class MyService : IService<MyRequest, MyResponse> 
{ 
    public MyResponse Execute(MyRequest request) 
    { 
     return new MyResponse(); 
    } 
} 

jetzt bin ich die Schaffung Fabrik, die meinen Dienst schaffen:

class ServicesFactory 
{ 
    public IService<RequestBase, ResponseBase> Create() 
    { 
     var service = new MyService(); 
     return (IService<RequestBase, ResponseBase>)service; 
    }  
} 

Das Problem ist, dass der Gusswurf Ausnahme.

Wie kann ich den abgeleiteten Typ auf den Basistyp umwandeln?

+0

Können Sie ein Tag für die von Ihnen verwendete Sprache hinzufügen? C# vielleicht? –

+0

Wenn Sie alles durch die Basisklassen drängen, gibt es keinen Grund, Generika zu verwenden. Ändern Sie Ihre Erstellungs- oder Fabriksignatur, um Typparameter einzubeziehen, wenn Sie eine statische Typisierung wünschen. Ansonsten können Sie auch einfach das Objekt oder die Basistypen verwenden. –

+0

Dies ist natürlich nur ein vereinfachtes Beispiel für meinen Code, aber ich brauche diese Hierarchie – eitanby

Antwort

3

Machen Sie Ihre Schnittstelle covariant auf TResponse:

public interface IService<TRequest, out TResponse> 

und Sie werden in der Lage MyService-IService<MyRequest, ResponseBase> zu konvertieren. Beachten Sie, dass eine Konvertierung in IService<RequestBase, ResponseBase> nicht möglich ist, da nicht alle RequestBase s MyRequest s sind.

Das heißt, Sie können MyService mit einer anderen Klasse dekorieren, die zur Laufzeit überprüft, ob in RequestBase tatsächlich MyRequest übergeben wird. Dies verletzt natürlich LSP, wenn die Schnittstelle RequestBase erwartet.

+0

Ich habe es versucht, aber es hat nicht funktioniert. Ich habe auch versucht, eine Schnittstelle zu meiner RequestBase und ResponseBase hinzuzufügen und dann zu IService zu konvertieren. Bei beiden Gelegenheiten bekomme ich die Ausnahme Kann Objekt des Typs "Playground.MyService" nicht auf "Playground.IService'2 [Playground.RequestBase, Playground.ResponseBase]" eingeben. – eitanby

+0

Das out-Schlüsselwort bezeichnet * co * variance (und das out-Schlüsselwort ist hier korrekt; die Schnittstelle ist tatsächlich kovariant über TResponse), nicht contravariance (was durch das in-Schlüsselwort bezeichnet wird). – Kyle

+0

@Kyle Richtig, ich verwechsle sie immer. Festsetzung. – milleniumbug