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

#c#

Вопрос:

Если у меня есть:

 void MyMethod(Object obj) {   ...   }
 

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

Комментарии:

1. Известен ли тип во время компиляции?

2. И чего вы ожидаете от этого добиться? Пожалуйста, расскажите нам, чего вы пытаетесь достичь, а не как вы ожидаете этого достичь.

3. @JonSkeet: Я хочу иметь возможность вызывать функцию из объекта. В настоящее obj.MyFunction(); время не компилируется, хотя я знаю, что у реального объекта есть эта функция.

4. @Полласситер: Если вы не знаете тип, что объявляет MyFunction метод?

5. если вы хотите вызвать метод для этого объекта, почему бы вам не реализовать интерфейс и не вызвать его в своем методе myMethod(IMyInterface obj)?

Ответ №1:

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

 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?

2. Неважно, найдено as для типизации и type(of: ClassName) функции для проверки типа экземпляра.

Ответ №2:

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

 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;
        ...
    }
}
 

Комментарии:

1. Отражение объекта типа object не приведет к «фактическому типу» объекта, как просил ОП. Кроме того, ваша логика myMethod ошибочна, потому что obj может быть типа A, а также может быть типа B. Ваша логика не предоставляет «фактический тип» (как просил ОП) — она предоставляет совместимый тип, и при этом не обязательно желаемый тип.

2. используйте obj. GetType(). Это определенно вернет его фактический тип.

3. Мы уже знаем «Тип». Он хочет, чтобы это разрешилось, как если бы это было «Т»

Ответ №3:

Как насчёт

 JsonConvert.DeserializeObject<SomeType>(object.ToString());
 

Комментарии:

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

Ответ №4:

В моем случае 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

Ответ №5:

Если ваш 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();
}
 

Ответ №6:

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

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

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

Ответ №7:

Если возможно несколько типов, сам метод не знает тип для приведения, но вызывающий знает, вы можете использовать что-то вроде этого:

 void TheObliviousHelperMethod<T>(object obj) {
    (T)obj.ThatClassMethodYouWantedToInvoke();
}

// Meanwhile, where the method is called:
TheObliviousHelperMethod<ActualType>(obj);
 

Ограничения на тип могут быть добавлены с помощью where ключевого слова после круглых скобок.

Ответ №8:

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

Ответ №9:

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

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

Комментарии:

1. Это нелогично. На самом деле вы не знаете настоящего типа. Как ты собираешься это сделать?