Как привести объект к его фактическому типу?

121

Если бы у меня был:

void MyMethod(Object obj) {   ...   }

Как я могу привести objего к фактическому типу?

Пол Ласситер
источник
2
Известен ли тип во время компиляции?
psubsee2003 02
1
И чего вы ожидаете от этого? Пожалуйста, расскажите нам, чего вы пытаетесь достичь, а не как вы рассчитываете достичь этого.
Джон Скит,
@JonSkeet: я хочу иметь возможность вызывать функцию из объекта. В настоящее время obj.MyFunction();не компилируется, хотя я знаю, что у реального объекта есть эта функция.
Пол Ласситер
@ psubsee2003: нет, это не так, потому что это ссылка на объект, передаваемая через взаимодействие.
Пол Ласситер
3
@PaulLassiter: Если вы не знаете тип, что объявляет MyFunctionметод?
Джон Скит,

Ответы:

194

Если вы знаете фактический тип, просто:

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

Если вы не знаете фактический тип, тогда: не совсем, нет. Вместо этого вам придется использовать одно из:

  • отражение
  • реализация известного интерфейса
  • динамический

Например:

// 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();
Марк Гравелл
источник
1
Какой эквивалентный синтаксис в Swift?
Нагендра Рао
1
Неважно, найдено asдля приведения типов и type(of: ClassName)функция для проверки типа экземпляра.
Нагендра Рао
43

Я не думаю, что вы можете (не без размышлений), вы также должны указать тип своей функции:

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

UPD :

Это может сработать для вас:

void MyMethod(Object obj)
{
    if (obj is A)
    {
        A a = obj as A;
        ...
    } 
    else if (obj is B)
    {
        B b = obj as B;
        ...
    }
}
Максим Ви.
источник
4
Это действительно бесполезный ответ, не заслуживающий голосов "за". Отражение объекта типа object не даст «фактического типа» объекта, как того требует OP. Кроме того, ваша логика MyMethod ошибочна, потому что obj может иметь тип A, а также может иметь тип B. Ваша логика не предоставляет «фактический тип» (как запрошено OP) - она ​​предоставляет совместимый тип, и не обязательно желаемый тип при этом.
Jazimov 03
используйте obj.GetType (). Это обязательно вернет его фактический тип.
JSON
3

Как насчет JsonConvert.DeserializeObject (object.ToString ());

Альбин
источник
Это неудовлетворительный ответ. Вопрос OP не имеет ничего общего с Json или сериализацией.
@ user12637955 на самом деле это рабочий ответ, но он имеет большую сложность из-за упаковки и распаковки, то есть объект -> ToString () -> конкретный тип. Если быть более точным, это должно выглядеть так:var myType = JsonConvert.DeserializeObject<MyType>(object.ToString());
Coke
1

В моем случае AutoMapper работает хорошо.

AutoMapper может отображать / из динамических объектов без какой-либо явной конфигурации:

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

Точно так же вы можете отображать объекты прямо из словарей, AutoMapper сопоставит ключи с именами свойств.

подробнее https://github.com/AutoMapper/AutoMapper/wiki/Dynamic-and-ExpandoObject-Mapping

Сорен
источник
1

Этот метод может быть не самым эффективным, но он прост и выполняет свою работу.

Он выполняет две операции: сначала он вызывает .ToString (), который в основном представляет собой сериализацию, а затем десериализацию с использованием Newtonsoft nuget (который вы должны установить).

public T Format<T>(Object obj) =>
    JsonConvert.DeserializeObject<T>(obj.ToString());
bombek
источник
Кратко опишите свой ответ для будущих читателей.
Сурадж Кумар
0

Если ваш MyFunction()метод определен только в одном классе (и его потомках), попробуйте

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

Если у вас есть большое количество несвязанных классов, определяющих функцию, которую вы хотите вызвать, вы должны определить интерфейс и сделать так, чтобы ваши классы определяли этот интерфейс:

interface IMyInterface
{
    void MyFunction();
}

void MyMethod(Object obj) 
{
    var o = obj as IMyInterface;
    if (o != null)
        o.MyFunction();
}
devio
источник
0

Приведите его к его реальному типу, если вы теперь используете тип, например, он ориентирован из класса с именем abc. Вы можете вызвать свою функцию таким образом:

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

если вы не знаете функцию, это можно сделать по-другому. Не всегда просто. Но каким-то образом его можно найти по подписи. Если это ваш случай, сообщите нам об этом.

Масуд
источник
-1

Приведение к фактическому типу очень просто:

void MyMethod(Object obj) {
    ActualType actualyType = (ActualType)obj;
}
user1610694
источник
8
Это нелогично. На самом деле вы не знаете, какой именно тип. Как ты должен это сделать?
Аллен Линаток,
-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 );
}
Хасан Бутуга
источник