Jak rzutować Object na jego rzeczywisty typ?

121

Jeżeli mam:

void MyMethod(Object obj) {   ...   }

Jak mogę rzutować objna jaki jest jego rzeczywisty typ?

Paul Lassiter
źródło
2
Czy typ jest znany w czasie kompilacji?
psubsee2003
1
A czego spodziewasz się z tego osiągnąć? Powiedz nam, co chcesz osiągnąć, a nie jak spodziewasz się tego osiągnąć.
Jon Skeet
@JonSkeet: Chcę mieć możliwość wywołania funkcji z obiektu. Obecnie obj.MyFunction();nie kompiluje się, chociaż wiem, że rzeczywisty obiekt ma taką funkcję.
Paul Lassiter
@ psubsee2003: nie, nie, ponieważ jest to odwołanie do obiektu przekazywane przez interop.
Paul Lassiter
3
@PaulLassiter: Jeśli nie znasz typu, co deklaruje MyFunctionmetodę?
Jon Skeet

Odpowiedzi:

194

Jeśli znasz rzeczywisty typ, po prostu:

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

Jeśli nie znasz konkretnego typu, to: nie do końca, nie. Zamiast tego musiałbyś użyć jednego z:

  • odbicie
  • implementacja dobrze znanego interfejsu
  • dynamiczny

Na przykład:

// 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
źródło
1
Jaka jest równoważna składnia w języku Swift?
Nagendra Rao
1
Nieważne, znalezione asdo rzutowania type(of: ClassName)typów i funkcji sprawdzającej typ instancji.
Nagendra Rao
43

Myślę, że nie możesz (nie bez refleksji), powinieneś także podać typ swojej funkcji:

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

UPD :

To może Ci pomóc:

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.
źródło
4
To naprawdę bezużyteczna odpowiedź, nie zasługująca na pozytywne głosy. Odbicie obiektu typu object nie da „rzeczywistego typu” obiektu, o co prosi OP. Ponadto logika MyMethod jest wadliwa, ponieważ obiekt może być typu A, a także może być typu B. Twoja logika nie dostarcza "rzeczywistego typu" (zgodnie z żądaniem OP) - zapewnia zgodny typ i niekoniecznie pożądany typ.
Jazimov
użyj obj.GetType (). To na pewno zwróci jego rzeczywisty typ.
JSON
3

A co z JsonConvert.DeserializeObject (object.ToString ());

albin
źródło
To nie jest satysfakcjonująca odpowiedź. Pytanie OP nie ma nic wspólnego z Jsonem ani serializacją.
@ user12637955 jest to właściwie działająca odpowiedź, ale ma większą złożoność ze względu na boxing i unboxing, tj. obiekt -> ToString () -> do konkretnego typu. Aby być dokładniejszym, powinno to wyglądać tak:var myType = JsonConvert.DeserializeObject<MyType>(object.ToString());
Coke
1

W moim przypadku AutoMapper działa dobrze.

AutoMapper może mapować do / z obiektów dynamicznych bez żadnej jawnej konfiguracji:

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);

Podobnie możesz mapować bezpośrednio ze słowników do obiektów, AutoMapper ustawi klucze w linii z nazwami właściwości.

więcej informacji https://github.com/AutoMapper/AutoMapper/wiki/Dynamic-and-ExpandoObject-Mapping

Soren
źródło
1

Ta metoda może nie być najbardziej wydajna, ale jest prosta i spełnia swoje zadanie.

Wykonuje dwie operacje: najpierw wywołuje .ToString (), który jest zasadniczo serializacją, a następnie deserializację przy użyciu nuget Newtonsoft (który należy zainstalować).

public T Format<T>(Object obj) =>
    JsonConvert.DeserializeObject<T>(obj.ToString());
bombek
źródło
Powinieneś krótko opisać swoją odpowiedź przyszłym czytelnikom.
Suraj Kumar
0

Jeśli twoja MyFunction()metoda jest zdefiniowana tylko w jednej klasie (i jej potomkach), spróbuj

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

Jeśli masz dużą liczbę w niepowiązanych klasach definiujących funkcję, którą chcesz wywołać, powinieneś zdefiniować interfejs i sprawić, by klasy definiowały ten interfejs:

interface IMyInterface
{
    void MyFunction();
}

void MyMethod(Object obj) 
{
    var o = obj as IMyInterface;
    if (o != null)
        o.MyFunction();
}
devio
źródło
0

Przerzuć go na jego rzeczywisty typ, jeśli teraz typ, na przykład jest zorientowany z klasy o nazwie abc. Możesz wywołać swoją funkcję w ten sposób:

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

jeśli nie znasz funkcji, możesz to zrobić w inny sposób. Nie zawsze łatwo. Ale możesz to znaleźć w jakiś sposób po jego sygnaturze. Jeśli tak jest w Twoim przypadku, daj nam znać.

Masoud
źródło
-1

Rzutowanie na rzeczywisty typ jest łatwe:

void MyMethod(Object obj) {
    ActualType actualyType = (ActualType)obj;
}
user1610694
źródło
8
To jest nielogiczne. Właściwie nie znasz rzeczywistego typu. Jak masz to zrobić?
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
źródło