Reputation: 425
I'm trying to use TypeSharp.
So far, I only had to use shapeof<'T>
in a following manner:
type AwsConfig = {
AccessKeyId : string
DefaultRegion : string
SecretAccessKey : string
}
let targetTypeShape = shapeof<AwsConfig> //targetTypeShape is of type targetTypeShape<AwsConfig>
match targetTypeShape with
| Shape.FSharpRecord (:? ShapeFSharpRecord<AwsConfig> as shape) -> foo shape
// 'shape' is of type ShapeFSharpRecord<AwsConfig>, which is important //
| _ -> failwith "some other cases"
But now I'd like to create dynamically shapeof
like
let awsConfigInstance = {AccessKeyId="123";DefaultRegion="asd";SecretAccessKey="asddd"}
let awsType = awsConfigInstance.GetType()
let targetTypeShape = shapeof<awsType> //that doesn't compile obviously
So i though i could do something like this
let typeShape = TypeShape.Create (awsConfigInstance.GetType())
match typeShape with
//'shape' is of type IShapeFSharpRecord not ShapeFSharpRecord<AwsConfig> as i need it too be
| Shape.FSharpRecord shape->
let castedShape = shape :?> ShapeFSharpRecord<_> //error
foo castedShape
the error on line shape :?> ShapeFSharpRecord<_>
is as follows:
System.InvalidCastException: 'Unable to cast object of type
'ShapeFSharpRecord`1[FsConfig.Tests.Common+AwsConfig]' to type
'ShapeFSharpRecord`1[Microsoft.FSharp.Core.FSharpOption`1[FsConfig.Tests.Common+AwsConfig]]'.'
I also tried to this trick:
let typeShape = TypeShape.Create (awsConfigInstance.GetType())
match typeShape with
//'shape' is of type IShapeFSharpRecord not ShapeFSharpRecord<AwsConfig> as i need it too be
| Shape.FSharpRecord shape->
let temp = Activator.CreateInstanceGeneric<ShapeFSharpRecord<_>>([|typeShape .Type|], [||])
let castedShape = temp :?> ShapeFSharpRecord<_> //error
foo castedShape
Error is on line let castedShape = temp :?> ShapeFSharpRecord<_>
'Unable to cast object of type 'ShapeFSharpRecord`1[FsConfig.Tests.Common+AwsConfig]'
to type 'ShapeFSharpRecord`1[Microsoft.FSharp.Core.FSharpOption`1[FsConfig.Tests.Common+AwsConfig]]'.'
I have no clue where is Microsoft.FSharp.Core.FSharpOption
coming from.
Any ideas how could i dynamically create ShapeFSharpRecord instance?
Upvotes: 0
Views: 115
Reputation: 17038
I don't know anything about TypeShape, but I've just looked at its source code a bit and reproduced what you're seeing. Unfortunately, I think the short answer is just "you can't do that".
To be more specific, if you want access to the underlying shape of an FSharpRecord
, then you have to know its type at compile time. If you try to finesse it by casting to ShapeFSharpRecord<_>
, the compiler isn't able to infer the type and uses obj
(i.e. System.Object
) instead.
So, the actual type of the shape is ShapeFSharpRecord<AwsConfig>
, but you're trying to cast it to a ShapeFSharpRecord<obj>
, which can't be done and results in a runtime exception.
(I'm ignoring issues related to the signature of the foo
function, which I don't think are central to your question.)
Upvotes: 1