2012-09-02 11 views
71

Wenn ich habe:Wie man Objekt auf seinen tatsächlichen Typ wirft?

void MyMethod(Object obj) { ... } 

Wie ich sein tatsächlicher Typ ist werfen kann obj zu dem, was?

+2

Ist die Art zum Zeitpunkt der Kompilierung bekannt? – psubsee2003

+1

Und was erwarten Sie von diesem zu erreichen? Bitte teilen Sie uns mit, was Sie erreichen möchten und nicht wie Sie es erreichen möchten. –

+0

@JonSkeet: Ich möchte eine Funktion aus dem Objekt aufrufen können. Derzeit 'obj.MyFunction();' kompiliert nicht, obwohl ich weiß, dass das reale Objekt diese Funktion hat. –

Antwort

117

Wenn Sie die tatsächliche Art kennen, dann nur:

SomeType typed = (SomeType)obj; 
typed.MyFunction(); 

Wenn Sie den tatsächlichen Typen nicht kennen, dann: nicht wirklich, Nein. Sie müssten stattdessen einen von verwenden:

  • Reflexion
  • Implementierung eine bekannte Schnittstelle
  • dynamische

Zum Beispiel:

// reflection 
obj.GetType().GetMethod("MyFunction").Invoke(obj, null); 

// interface 
IFoo foo = (IFoo)obj; // where SomeType : IFoo and IFoo declares MyFunction 
foo.MyFunction(); 

// dynamic 
dynamic d = obj; 
d.MyFunction(); 
+0

Was ist die äquivalente Syntax in Swift? – Rao

+1

Nevermind, gefunden 'as' für typecasting und' type (of: ClassName) 'Funktion, um den Instanztyp zu prüfen. – Rao

0

zu tatsächlichem Typ Casting ist einfach:

void MyMethod(Object obj) { 
    ActualType actualyType = (ActualType)obj; 
} 
+4

das ist sehr lustig ... – Steve

+1

Das ist unlogisch. Sie kennen den eigentlichen Typ eigentlich nicht. Wie soll das gemacht werden? –

28

Ich glaube nicht, Sie können (nicht ohne Reflexion) auch einen Typ für Ihre Funktion angeben:

void MyMethod(Object obj, Type t) 
{ 
    var convertedObject = Convert.ChangeType(obj, t); 
    ... 
} 

UPD:

Dies kann für Sie arbeiten:

void MyMethod(Object obj) 
{ 
    if (obj is A) 
    { 
     A a = obj as A; 
     ... 
    } 
    else if (obj is B) 
    { 
     B b = obj as B; 
     ... 
    } 
} 
+1

Dies ist wirklich eine sinnlose Antwort, die Up-Stimmen nicht verdient. Die Reflexion eines Objekts vom Typ Objekt ergibt nicht den "tatsächlichen Typ" des Objekts, wie von OP gefordert. Außerdem ist Ihre MyMethod-Logik fehlerhaft, weil obj vom Typ A sein kann und auch vom Typ B sein kann. Ihre Logik liefert nicht den "tatsächlichen Typ" (wie von OP angefordert) - sie stellt einen kompatiblen Typ zur Verfügung und nicht unbedingt der gewünschte Typ dazu. – Jazimov

0
Implement an interface to call your function in your method 
interface IMyInterface 
{ 
void MyinterfaceMethod(); 
} 

IMyInterface MyObj = obj as IMyInterface; 
if (MyObj != null) 
{ 
MyMethod(IMyInterface MyObj); 
} 
0

Wenn Ihr MyFunction() Methode nur in einer Klasse definiert ist (und seine Nachkommen), versuchen

void MyMethod(Object obj) 
{ 
    var o = obj as MyClass; 
    if (o != null) 
     o.MyFunction(); 
} 

Wenn Sie haben eine große Anzahl in keinem Zusammenhang Klassen definieren, die Funktion, die Sie aufrufen möchten, sollten Sie eine Schnittstelle definieren und Ihre Klassen, die eine Schnittstelle zu definieren machen:

interface IMyInterface 
{ 
    void MyFunction(); 
} 

void MyMethod(Object obj) 
{ 
    var o = obj as IMyInterface; 
    if (o != null) 
     o.MyFunction(); 
} 
0

Guss es zu seiner realen Typ, wenn Sie jetzt den Typ es zum Beispiel orientiert sich an der Klasse abc. Sie können Ihre Funktion auf diese Weise nennen:

(abc)(obj)).MyFunction(); 

wenn Sie die Funktion nicht wissen, dass es in einer anderen Art und Weise durchgeführt werden kann. Nicht immer einfach. Aber Sie können es in irgendeiner Weise durch seine Unterschrift finden. Wenn dies der Fall ist, sollten Sie uns Bescheid geben.

0

In meinem Fall funktioniert AutoMapper gut.

AutoMapper können ohne explizite Konfiguration zu/von dynamischen Objekten zuordnen:

public class Foo { 
    public int Bar { get; set; } 
    public int Baz { get; set; } 
} 
dynamic foo = new MyDynamicObject(); 
foo.Bar = 5; 
foo.Baz = 6; 

Mapper.Initialize(cfg => {}); 

var result = Mapper.Map<Foo>(foo); 
result.Bar.ShouldEqual(5); 
result.Baz.ShouldEqual(6); 

dynamic foo2 = Mapper.Map<MyDynamicObject>(result); 
foo2.Bar.ShouldEqual(5); 
foo2.Baz.ShouldEqual(6); 

Ebenso können Sie direkt aus den Wörterbüchern zu Objekten zuordnen, AutoMapper die Schlüssel mit Eigenschaftsnamen übereinstimmen.

weitere Informationen https://github.com/AutoMapper/AutoMapper/wiki/Dynamic-and-ExpandoObject-Mapping

Verwandte Themen