2010-03-29 3 views
7

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

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

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

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

, который хорошо и хорошо.^___^

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

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

Как должна один идет о решении этой проблемы?

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

+0

Я отправил некоторый пример кода, как я решил эту проблему [здесь] [ 1] [1]: http://stackoverflow.com/questions/914578/using-type-returned-by-type-gettype-in-c-sharp/8903800#8903800 –

ответ

5

Вы должны продолжать использовать 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.

+0

@Richard Нил Ilagan : Ну ... есть * некоторые * удачи. Следующий месяц (ish) Microsoft выпускает VS 2010 и .NET 4. Когда это произойдет, вы сможете делать именно то, что вы хотите написать в своем вопросе; ключевое слово 'dynamic', которое я упомянул в своем ответе, будет привязываться к методу во время выполнения, а не к компиляции (что означает, что вы получите исключение во время выполнения, если метод не существует, а не ошибка компилятора). Вы можете обманывать с .NET 4 бесплатно * сейчас *, используя выпускной выпуск VS2010. – Randolpho

+0

Возможно, вы также найдете Fasterflect (http://fasterflect.codeplex.com), представляющий интерес. Это библиотека, предназначенная для того, чтобы сделать отражение проще и быстрее благодаря генерации кода. Позволяет делать аккуратные вещи, такие как вызов наилучшего соответствия перегрузки, заданный набором параметров, а также более простой материал. –

+0

@ Randolpho ~ yeap! Я на самом деле немного взволнован по поводу этого аспекта .NET4. Здесь мы надеемся, что мы сможем перенести наши приложения прямо с самого начала! :) @Morten ~ большое спасибо! Это, безусловно, сделает мой lib-код помощника. :) –

3

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

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

4

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

obj.GetType().InvokeMember(
    "MyMethod", 
    BindingFlags.Public | BindingFlags.Instance | BindingFlags.InvokeMethod, 
    null, 
    obj, 
    null 
); 
+2

+1. Любите эту первую линию. Я должен сыграть в игру до конца, мужик. * edit * Кроме того, я просто проиграл игру. – Randolpho

1

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

MethodInfo method = genType.GetMethod("MyMethod"); 
method.Invoke(obj, null); 
2

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

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

в противном случае, использование отражения для доступа к самому методу, как было предложено @Aar onaught.

0

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

0

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

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

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(); 
Смежные вопросы