Использование объекта Type для создания универсального - PullRequest
7 голосов
/ 30 марта 2010

Я пытаюсь создать экземпляр универсального класса, используя объект Type.

По сути, у меня будет коллекция объектов различных типов во время выполнения, и, поскольку точно не известно, какими именно они будут, я думаю, что мне придется использовать Reflection.

Я работал над чем-то вроде:

Type elType = Type.GetType(obj);
Type genType = typeof(GenericType<>).MakeGenericType(elType);
object obj = Activator.CreateInstance(genType);

Что хорошо и хорошо. ^ ___ ^

Проблема в том, что я хотел бы получить доступ к методу моего экземпляра GenericType <>, который я не могу, потому что он типизирован как объектный класс. Я не могу найти способ преобразовать его в конкретный GenericType <>, потому что это была проблема в первую очередь (то есть я просто не могу вставить что-то вроде:)

((GenericType<elType>)obj).MyMethod();

Как можно решить эту проблему?

Большое спасибо! ^ ___ ^

Ответы [ 7 ]

5 голосов
/ 30 марта 2010

Вы должны продолжить использовать Reflection для вызова фактического метода:

// Your code
Type elType = Type.GetType(obj);
Type genType = typeof(GenericType<>).MakeGenericType(elType);
object obj = Activator.CreateInstance(genType);

// To execute the method
MethodInfo method = genType.GetMethod("MyMethod",
    BindingFlags.Instance | BindingFlags.Public);
method.Invoke(obj, null);

Для получения дополнительной информации см. Type.GetMethod и MethodBase.Invoke .

4 голосов
/ 30 марта 2010

Как только вы начинаете игру с отражением, вы должны играть в нее до конца.Тип не известен во время компиляции, поэтому вы не можете его привести.Вам нужно будет вызвать метод с помощью отражения:

obj.GetType().InvokeMember(
    "MyMethod", 
    BindingFlags.Public | BindingFlags.Instance | BindingFlags.InvokeMethod, 
    null, 
    obj, 
    null
);
3 голосов
/ 30 марта 2010

В C # 3.5 вы должны использовать Type.GetMethod и MethodInfo.Invoke для вызова метода.

В C # 4 вы можете использовать ключевое слово dynamic и связываться с методом во время выполнения.

2 голосов
/ 30 марта 2010

Самый простой подход - извлечь не универсальный супертип (базовый класс или интерфейс) из GenericType, который содержит методы, которые вы хотите использовать для этой цели:

class GenericType<T> : GenericBase { ... }
class GenericBase { abstract void MyMethod(); }

Если это не так, используйте отражение, чтобы получить доступ к самому методу, предложенному @ Aaronaught.

1 голос
/ 30 марта 2010

После создания экземпляра просто выполните:

MethodInfo method = genType.GetMethod("MyMethod");
method.Invoke(obj, null);
0 голосов
/ 30 марта 2010

Я не уверен, насколько различаются ваши типы или если у вас есть контроль над методами, которые вы будете вызывать в них, но может быть полезно создать интерфейс, который определяет, какой набор функций вы собираетесь звонить Поэтому после создания экземпляра вы можете привести его к интерфейсу и вызвать любые нужные вам функции.

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

interface IMyInterface
{
   void A();
   int  B();
}

class One : IMyInterface
{
   ...
   implement A and B
   ...
}

Type elType = Type.GetType(obj);
Type genType = typeof(GenericType<>).MakeGenericType(elType);
IMyInterface obj = (IMyInterface)Activator.CreateInstance(genType);
obj.A();
0 голосов
/ 30 марта 2010

Если вам известна сигнатура методов, которые вы хотите вызвать, вы можете не только использовать MethodInfo.Invoke(), как показано в других примерах, но и создать делегат, который обеспечивает более эффективный вызов (если вам нужно вызвать тот же метод несколько раз), используя Delegate.CreateDelegate().

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...