Wie kann man das Objekt auf seinen tatsächlichen Typ umwandeln?

120

Wenn ich habe:

void MyMethod(Object obj) {   ...   }

Wie kann ich objauf den tatsächlichen Typ umstellen?

Paul Lassiter
quelle
2
Ist der Typ zur Kompilierungszeit bekannt?
psubsee2003
1
Und was erwarten Sie davon? Bitte sagen Sie uns, was Sie erreichen möchten und nicht, wie Sie es erwarten.
Jon Skeet
@ JonSkeet: Ich möchte eine Funktion vom Objekt aus aufrufen können. Derzeit obj.MyFunction();wird nicht kompiliert, obwohl ich weiß, dass das reale Objekt diese Funktion hat.
Paul Lassiter
@ psubsee2003: nein, das ist nicht der Fall, da es sich um eine Objektreferenz handelt, die über Interop übergeben wird.
Paul Lassiter
3
@PaulLassiter: Wenn Sie den Typ nicht kennen, was deklariert die MyFunctionMethode?
Jon Skeet

Antworten:

195

Wenn Sie den tatsächlichen Typ kennen, dann einfach:

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

Wenn Sie den tatsächlichen Typ nicht kennen, dann: nicht wirklich, nein. Sie müssten stattdessen eines der folgenden Elemente verwenden:

  • Reflexion
  • Implementierung einer bekannten Schnittstelle
  • dynamisch

Beispielsweise:

// 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();
Marc Gravell
quelle
1
Was ist die äquivalente Syntax in Swift?
Nagendra Rao
1
Nevermind, gefunden asfür Typumwandlung und type(of: ClassName)Funktion zum Überprüfen des Instanztyps.
Nagendra Rao
42

Ich denke nicht, dass Sie dies können (nicht ohne Reflexion), Sie sollten 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 funktionieren:

void MyMethod(Object obj)
{
    if (obj is A)
    {
        A a = obj as A;
        ...
    } 
    else if (obj is B)
    {
        B b = obj as B;
        ...
    }
}
Maksim Vi.
quelle
4
Dies ist wirklich eine nutzlose Antwort, die keine Gegenstimmen 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, da obj vom Typ A und vom Typ B sein kann. Ihre Logik liefert nicht den "tatsächlichen Typ" (wie vom OP angefordert) - sie bietet einen kompatiblen Typ und nicht unbedingt der gewünschte Typ dazu.
Jazimov
benutze obj.GetType (). Das wird definitiv den tatsächlichen Typ zurückgeben.
JSON
3

Wie wäre es mit JsonConvert.DeserializeObject (object.ToString ());

Albin
quelle
Dies ist keine zufriedenstellende Antwort. Die Frage von OP hat nichts mit Json oder Serialisierung zu tun.
@ user12637955 Dies ist eigentlich eine funktionierende Antwort, hat aber aufgrund des Ein- und Auspackens eine größere Komplexität, dh Objekt -> ToString () -> zum konkreten Typ. Um genauer zu sein, sollte es so aussehen:var myType = JsonConvert.DeserializeObject<MyType>(object.ToString());
Cola
1

In meinem Fall funktioniert AutoMapper gut.

AutoMapper kann dynamischen Objekten ohne explizite Konfiguration zugeordnet werden:

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 Objekte direkt von Wörterbüchern zuordnen. AutoMapper richtet die Schlüssel mit Eigenschaftsnamen aus.

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

Soren
quelle
0

Wenn Ihre MyFunction()Methode nur in einer Klasse (und ihren Nachkommen) definiert ist, versuchen Sie es

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

Wenn Sie eine große Anzahl in nicht verwandten Klassen haben, die die Funktion definieren, die Sie aufrufen möchten, sollten Sie eine Schnittstelle definieren und Ihre Klassen diese Schnittstelle definieren lassen:

interface IMyInterface
{
    void MyFunction();
}

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

Wandeln Sie es in seinen realen Typ um, wenn Sie jetzt den Typ verwenden, der sich beispielsweise an der Klasse abc orientiert. Sie können Ihre Funktion folgendermaßen aufrufen:

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

Wenn Sie die Funktion nicht kennen, können Sie sie auf andere Weise ausführen. Nicht immer einfach. Aber Sie können es irgendwie durch seine Unterschrift finden. Wenn dies Ihr Fall ist, sollten Sie uns dies mitteilen.

Masoud
quelle
0

Diese Methode ist möglicherweise nicht die effizienteste, aber einfach und erledigt die Aufgabe.

Es führt zwei Operationen aus: Erstens ruft es .ToString () auf, das im Grunde eine Serialisierung ist, und dann die Deserialisierung mit Newtonsoft Nuget (das Sie installieren müssen ).

public T Format<T>(Object obj) =>
    JsonConvert.DeserializeObject<T>(obj.ToString());
bombek
quelle
Sie sollten Ihre Antwort für die zukünftigen Leser kurz beschreiben.
Suraj Kumar
-1

Das Casting auf den tatsächlichen Typ ist einfach:

void MyMethod(Object obj) {
    ActualType actualyType = (ActualType)obj;
}
user1610694
quelle
8
Das ist unlogisch. Sie kennen den tatsächlichen Typ eigentlich nicht. Wie soll man das machen?
Allen Linatoc
-2
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 );
}
Hassan Boutougha
quelle