Як передати об’єкт його фактичному типу?


121

Якщо я маю:

void MyMethod(Object obj) {   ...   }

Як я можу сказати, objщо таке його фактичний тип?


2
Чи відомий тип під час компіляції?
psubsee2003

1
І що ви очікуєте від цього досягти? Скажіть, будь ласка, чого ви намагаєтесь досягти, а не як ви розраховуєте досягти цього.
Джон Скіт

@JonSkeet: Я хочу мати можливість викликати функцію від об'єкта. В даний час obj.MyFunction();не компілюється, хоча я знаю, що реальний об'єкт має таку функцію.
Пол Лассітер

@ psubsee2003: ні, це не так, оскільки це посилання на об'єкт передається через interop.
Пол Лассітер

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?
Nagendra Rao

1
Nevermind, знайдено asдля набору типів даних та type(of: ClassName)функції перевірки типу екземпляра.
Nagendra Rao

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
Це дійсно марна відповідь, яка не заслуговує на голосування. Відображення об'єкта об'єкта типу не призведе до "фактичного типу" об'єкта, як це запитує ОП. Крім того, ваша логіка MyMethod є помилковою, оскільки obj може бути типу A, а також може бути типу B. Ваша логіка не забезпечує "фактичного типу" (як вимагає ОП) - вона забезпечує сумісний тип, і не обов'язково бажаний тип при цьому.
Язимов

використовувати obj.GetType (). Це, безумовно, поверне фактичний тип.
JSON

3

Як щодо JsonConvert.DeserializeObject (object.ToString ());


Це не задовольняюча відповідь. Питання ОП не має нічого спільного з Json або серіалізацією.

@ user12637955 це насправді робоча відповідь, але вона має більшу складність, завдяки боксу та розпакуванню, тобто об'єкт -> ToString () -> до конкретного типу. Якщо точніше, це має виглядати так:var myType = JsonConvert.DeserializeObject<MyType>(object.ToString());
Кокс

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 (який потрібно встановити).

public T Format<T>(Object obj) =>
    JsonConvert.DeserializeObject<T>(obj.ToString());

Ви повинні коротко описати свою відповідь для майбутніх читачів.
Сурай Кумар

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

0

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

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

якщо ви не знаєте функції, це можна зробити по-іншому. Не завжди легко. Але ви можете знайти його якось за своїм підписом. Якщо це ваш випадок, ви повинні повідомити нам про це.


-1

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

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

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 );
}
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.