Let's say we have the following type which does nothing for the moment
type Foo<'a,'b> =
new () = {}
We want to instanciate it like this
type First = class end
let first = new Foo<First,First>()
And what I want to do right now is to instanciate the next object to be something like
let second = new Foo<first.GetType(),First>()
However I can't do first.GetType()
to provide it with a type. So I thought of binding the type to a value of type System.Type
and use it like the following
let typing = first.GetType()
let second = new Foo<typing,First>()
But it says that the type typing
is not defined, instead of taking the type of first
.
How can I be able to do something like let second = new Foo<first.getType(),First>()
?
Edit:
More details here about what I am trying to aim for:
let's say we have a protocol of communication on a channel channel
. The protocol of communication is defined using a Map like the following :
[(currentState:Int , nextState:Int , type:string , label:string) -> realType:Type ]
for instance
[(currentState:1 , nextState:2 , type:"send" , label:"hello()") -> realType:Hello ;
(currentState:2 , nextState:3 , type:"receive" , label:"bye()") -> realType:Bye]
What I want from that is to generate the following functions
send(a:Hello)
receive(a:Bye)
but such that, as you can see in the Map, receive(a:Bye)
cannot be done before send(a:Hello)
or there will be an error at compile-time. It should follow the correct sequence. That's the reason why to do that I want to instanciate a type of type receiveType as the return value of the send(a:Hello)
function allowing me to use the receive(a:Bye)
in the following way :
channel.send(Hello()).receive(Bye())
The last thing is that the Map can have more states than these 2, the length depends on the protocol I use. And the whole idea will be implemented within a type provider so that I can provide types and methods that I just described using intelliSense.
Related question: F# generating types in a type extension function within a type provider
答案 0 :(得分:2)
实例化类型参数与现有对象不同的泛型类型的实例,可以在运行时使用方法GetGenericTypeDefinition
和MakeGenericType
完成。
所以,举个例子:
type Foo<'a,'b> =
new () = {}
type First = class end
let first = new Foo<First,First>()
步骤如下:
获取没有任何类型参数的泛型类型:
let genericFooType = first.GetType().GetGenericTypeDefinition()
使用适当的类型参数创建一个新的泛型类型:
let secondType = genericFooType.MakeGenericType(first.GetType(), typeof<First>)
通过适当的构造函数创建新类型的实例。在这种情况下,有一个没有参数的构造函数:
let second = secondType.GetConstructor([||]).Invoke([||])
second.GetType() = typeof<Foo<Foo<First,First>, First>> // True
如果您需要知道原始对象类型的任何类型参数,可以按如下方式检索它们:
let originalTypeArguments = first.GetType().GenericTypeArguments
// Prints [|"First"; "First"|]
printfn "%A" (originalTypeArguments |> Array.map (fun x -> x.Name))