Это мои 2 цента на основе ответа Grax , но с двумя параметрами, необходимыми для общего метода.
Предположим, что ваш метод определяется следующим образом в классе Helpers:
public class Helpers
{
public static U ConvertCsvDataToCollection(string csvData)
where U : ObservableCollection
{
//transform code here
}
}
В моем случае тип U всегда является наблюдаемым объектом хранения коллекции типа T.
Поскольку у меня есть предопределенные типы, я сначала создаю «фиктивные» объекты, которые представляют наблюдаемый набор (U) и объект, хранящийся в нем (T), и который будет использоваться ниже, чтобы получить их тип при вызове Make
object myCollection = Activator.CreateInstance(collectionType);
object myoObject = Activator.CreateInstance(objectType);
Затем вызовите GetMethod, чтобы найти вашу общую функцию:
MethodInfo method = typeof(Helpers).
GetMethod("ConvertCsvDataToCollection");
До сих пор вышеупомянутый вызов в значительной степени идентичен тому, что было объяснено выше, но с небольшой разницей, когда вам нужно передать ему несколько параметров.
Вам нужно передать массив Type [] в функцию MakeGenericMethod, которая содержит типы «фиктивных» объектов, которые были созданы выше:
MethodInfo generic = method.MakeGenericMethod(
new Type[] {
myCollection.GetType(),
myObject.GetType()
});
Как только это будет сделано, вам нужно вызвать метод Invoke, как указано выше.
generic.Invoke(null, new object[] { csvData });
И все готово.
UPDATE:
Поскольку @Bevan выделен, мне не нужно создавать массив при вызове функции MakeGenericMethod, поскольку он принимает параметры, и мне не нужно создавать объект, чтобы получить типы, поскольку я могу просто передать типы непосредственно этой функции. В моем случае, поскольку у меня есть типы, предопределенные в другом классе, я просто изменил свой код на:
object myCollection = null;
MethodInfo method = typeof(Helpers).
GetMethod("ConvertCsvDataToCollection");
MethodInfo generic = method.MakeGenericMethod(
myClassInfo.CollectionType,
myClassInfo.ObjectType
);
myCollection = generic.Invoke(null, new object[] { csvData });
myClassInfo содержит 2 свойства типа Type
, которые я установил во время выполнения на основе перечисления значение передается конструктору и предоставит мне соответствующие типы, которые затем я использую в MakeGenericMethod.
Еще раз спасибо за выделение этого @Bevan.
Похоже, у вас есть проблема со сборкой; Мне кажется, я помню, что я использовал ту самую страницу, на которую вы ссылаетесь, в качестве примера, когда писал интерфейс FFI в библиотеке Windows Win32 DDEML. Например, одна из используемых нами структур -
typedef struct tagHSZPAIR {
HSZ hszSvc;
HSZ hszTopic;
} HSZPAIR, *PHSZPAIR;
#include "ddeml.h"
переносит это в файл DDEML.hsc
. Мы обращаемся к нему с помощью:
data HSZPair = HSZPair HSZ HSZ instance Storable HSZPair where sizeOf _ = (#size HSZPAIR) alignment = sizeOf peek ptr = do svc <- (#peek HSZPAIR, hszSvc) ptr topic <- (#peek HSZPAIR, hszTopic) ptr return $ HSZPair svc topic poke ptr (HSZPair svc topic) = do (#poke HSZPAIR, hszSvc) ptr svc (#poke HSZPAIR, hszTopic) ptr topic
К сожалению, я не могу показать вам, что это компилируется в данный момент, потому что у меня нет под рукой окна Windows, но сгенерированный код был таким же, как указано выше, за исключением #size HSZPAIR
заменен на (64)
или что-то еще и так далее.
Основная поддержка FFI включает только скалярные типы. Все остальное Вы волнуете выполнение с адресной арифметикой. Эти раздел по внешним типам в документации FFI дает основы, и можно найти пример в Поваренная книга FFI .
Когда-то Вы могли использовать инструменты как зеленая карта и H/Direct , чтобы сгенерировать маршалинг и немаршалинг кода для Вас. По причинам я не понимаю, эти инструменты не были обновлены в долгое время. Насколько я могу сказать, что текущий предпочтительный инструмент hsc2hs
.
Редактирование: Как отмечено в комментарии (благодарит ephemient), c2hs
также популярно, и так как c2hs
от Manuel Chakravarty, это, вероятно, будет хорошо.
Hackage имеет несколько пакетов, которые используют FFI, на который Вы могли посмотреть для примеров.