2009-07-21 10 views
36

Kurz gesagt, ich habe eine C# -Funktion, die eine Aufgabe für einen bestimmten Typ ausführt, der als Objektinstanz übergeben wird. Alles funktioniert gut, wenn eine Klasseninstanz übergeben wird. Wenn das Objekt jedoch als Schnittstelle deklariert wird, möchte ich wirklich die konkrete Klasse finden und die Aktion für diesen Klassentyp ausführen.Suchen des konkreten Typs hinter einer Schnittstelleninstanz

Hier ist das allgegenwärtige schlechte Beispiel (glänzend mit falscher Eigenschaft Gehäuse usw.):

public interface IA 
{ 
    int a { get; set; } 
} 
public class B : IA 
{ 
    public int a { get; set; } 
    public int b { get; set; } 
} 
public class C : IA 
{ 
    public int a { get; set; } 
    public int c { get; set; } 
} 

// snip 

IA myBObject = new B(); 
PerformAction(myBObject); 

IA myCObject = new C(); 
PerformAction(myCObject); 

// snip 

void PerformAction(object myObject) 
{ 
    Type objectType = myObject.GetType(); // Here is where I get typeof(IA) 
    if (objectType.IsInterface) 
    { 
     // I want to determine the actual Concrete Type, i.e. either B or C 
     // objectType = DetermineConcreteType(objectType); 
    } 
    // snip - other actions on objectType 
} 

ich der Code in Perform möchte Reflexion verwenden dagegen Parameter sind und sieht, dass es nicht nur eine Instanz von IA ist aber das ist eine Instanz von B und die Eigenschaft "b" über GetProperties() zu sehen. Wenn ich .GetType() verwende, bekomme ich den Typ von IA - nicht was ich will.

Wie kann PerformAction den zugrunde liegenden Beton-Typ der Instanz von IA bestimmen?

Einige könnten versucht sein, die Verwendung einer abstrakten Klasse vorzuschlagen, aber das ist nur die Einschränkung meines schlechten Beispiels. Die Variable wird ursprünglich als Schnittstelleninstanz deklariert.

+7

Das klingt wie ein schlechtes Design. Sie sollten Polymorphismus verwenden, anstatt Ihre Methode über bestimmte konkrete Typen wissen zu lassen. Was passiert, wenn Sie später einen hinzufügen? –

+4

Schadet das nicht dem Zweck einer Schnittstelle? Sie sollten sich nicht darum kümmern, was der konkrete Typ ist, solange er die Schnittstelle implementiert. –

+2

+1 zu John und Chris, ist es nicht nur schlechtes Design, aber die Frage ergibt keinen Sinn. –

Antwort

56
Type objectType = myObject.GetType(); 

Sollten Sie noch die konkrete Art geben, nach Ihrem Beispiel.

+2

Ja, der aufrufende "myObject.GetType()" gibt NIEMALS den Schnittstellentyp zurück. – TcKs

+0

Der Parameter von 'PerfomAction' ist' Objekt', aber er konnte nicht: 'IA.getType()' für zB. –

2

Sie können nie Instanzen einer Schnittstelle haben. Es ist also nicht möglich, festzustellen, ob Sie mit einer Schnittstelle oder einem konkreten Typ zu tun haben, da Sie immer mit einem konkreten Typ arbeiten werden. Ich bin mir also nicht sicher, ob du eine Frage stellst. Was genau versuchst du zu tun und warum?

+2

+1 genau, in der Tat funktioniert sein Beispiel gut. –

5

Was Sie tun, ist wirklich Design Bett, aber Sie haben keine Reflektion verwenden Sie es wie diese

überprüfen
void PerformAction(object myObject) 
{ 
    B objectType = myObject as B; // Here is where I get typeof(IA) 
    if (objectType != null) 
    { 
     //use objectType.b 
    } 
    else 
    { 
     //Same with A 
    } 
    // snip - other actions on objectType 
} 
+2

Dies ist immer noch ein ziemlich schlechtes Design, da Sie immer noch auf den konkreten Typ angewiesen sind. Damit wird der Zweck, eine Schnittstelle zu haben, weitgehend zunichte gemacht ... – jrista

+0

Ich schreie in meinem Kopf: "LSP, ISP, DIP !!!!!!!!!!!!!!!!!!!! !!!!!!!!!!!!!!!! " – Sebastien

0

suchen Sie vielleicht für die is operator

void PerformAction(object myObject) 
{ 
    if (myObject is B) 
    { 
     B myBObject = myObject as B; 
     myBObject.b = 1; 
    } 

    if (myObject is C) 
    { 
     C myCObject = myObject as C; 
     myCObject.c = 1; 
    } 

    // snip - other actions on objectType 
} 
+0

Sie werfen es zweimal. Verwenden Sie sofort den 'as'-Operator und prüfen Sie später auf null – nawfal

4

ich über das schlechte Design zustimmen. Wenn Sie eine Schnittstelle haben, sollte es sein, weil Sie einige allgemeine Funktionalität verwenden müssen, ohne sich darum zu kümmern, was die konkrete Implementierung ist. Als Beispiel, klingt es wie die PerformAction-Methode sollte eigentlich ein Teil der Schnittstelle sein:

public interface IA 
{ 
    int a { get; set; } 
    void PerformAction(); 
} 

public class B: IA 
{ 
    public int a { get; set; } 
    public int b { get; set; } 

    public void PerformAction() 
    { 
     // perform action specific to B 
    } 
} 

public class C : IA 
{ 
    public int a { get; set; } 
    public int c { get; set; } 

    public void PerformAction() 
    { 
     // perform action specific to C 
    } 
} 

void PerformActionOn(IA instance) 
{ 
    if (instance == null) throw new ArgumentNullException("instance"); 

    instance.PerformAction(); 

    // Do some other common work... 
} 


B b = new B(); 
C c = new C(); 

PerformActionOn(b); 
PerformActionOn(c);