Если вы загружаете реализацию интерфейса с помощью Reflection, то с ним будет довольно сложно работать. Проблема в том, что вы получаете объект типа obj
. Вы знаете, что он реализует IFetchData<'T>
для некоторых 'T
, но статически вы не знаете, для каких 'T
. Это проблема, потому что вы не можете привести объект к более конкретному типу - если вы попытались использовать IFetchData<obj>
, он не будет работать, потому что вы не можете привести, например, IFetchData<int>
к этому типу.
Я бы рекомендовал использовать неуниверсальный интерфейс, который является довольно распространенным шаблоном .NET:
type IFetchDataUntyped =
abstract FetchData : string -> System.Collections.IEnumerable
type IFetchData<'T> =
inherit IFetchDataUntyped
abstract FetchData : string -> seq<'T>
Когда вы загружаете реализацию, используя Reflection, вы можете привести объект к IFetchDataUntyped
и работать с ним довольно разумным способом (используя Seq.cast
для преобразования последовательности в более конкретный тип, если вы знаете тип элемента) .
В зависимости от вашего приложения вы также можете просто сделать метод FetchData
универсальным методом и оставить интерфейс не универсальным. Затем вы можете привести динамически загруженные объекты к интерфейсу и вызвать метод. Однако это меняет дизайн (поскольку метод должен работать для любого типа, который он получает в качестве параметра типа):
type IFetchData =
abstract FetchData<'T> : string -> seq<'T> // Note: Generic parameter here!