F# 将匿名类型转换为结构记录

F# casting anonymous type to struct record

我从 c​​# 数据库服务中收集了简单的匿名对象(我可以查看它但不能修改代码),看起来像:

entities[InfoKey].Add(
    new
    {
        id = (int)result[0],
        mpvId = Convert.ToUInt32(result[1]),
        date = ((DateTime)result[2]).ToString("yyyy-MM-dd HH:mm:ss"),
        systemId = Convert.ToUInt32(result[3]),
        name = (string)result[4]
    });

现在在 f# 服务中,我可以实际做一些事情,我希望将其转换为记录(这样我就可以对其进行一些实际操作),所以我创建了类似的东西:

type private StatisticsInfoCursor = {
    Id: int;
    MpvId : uint32;
    Date : string; 
    SystemId : uint32;
    Name : string;
}

而且铸造操作看起来,还是应该很简单的:

let infoCursor = 
    try
        rawData.[StatisticsInfoRepository.InfoKey] 
        |> Seq.map 
            (fun v -> 
                let unboxObject = v |> unbox // THIS COUSES EXCEPTION
                {Id = unboxObject.Id; MpvCabinetId = unboxObject.MpvCabinetId; Date = unboxObject.Date; SystemId = unboxObject.SystemId; Name = unboxObject.Name})
    with 
        ex -> raise ex

还有一个简单的调用:

for data in infoCursor do
    printf "%i - %A" data.Id data.Date
()

但我得到的只是

Unable to cast object of type '<>f__AnonymousType19`5[System.Int32,System.UInt32,System.String,System.UInt32,System.String]' to type 'StatisticsInfoCursor'.

我做错了什么?

编辑:

我用反射做了这样的事情:

let GetPropertyValue (object : obj) propertyName =
   let objectType = object.GetType()
   let propertyInfo = objectType.GetProperty propertyName
   propertyInfo.GetValue object

(GetPropertyValue unboxObject "id") |> unbox; 

它有效,但不是太过分了,尤其是当可能有大量数据时??

我认为没有办法做到这一点。假设您有这样的 C# 代码:

public class A {
  public static List<object> GetThings() {
    var a = new List<object>();
    a.Add(new { foo=1, bar="hi" });
    return a;
  }
}

如评论中所述,.NET 使用名义类型,因此即使您从未命名类型,C# 编译器也会为其生成一些名称。在这种情况下,列表中实际对象的类型将是一些具有丑陋名称的私有类型。您可以使用 ildasm 等反编译工具找出这是什么,在我的例子中,它类似于 <>f__AnonymousType0`2.

事实证明,您甚至可以尝试在 F# 中使用它:

A.GetThings() |> Seq.map (fun a -> 
  let it = unbox<``<>f__AnonymousType0`2``<int, string>> a
  it )

IDE 知道这个类型,它甚至会告诉你它的成员是什么,但不幸的是(或者幸运的是......),这个类型被标记为 private 所以这给出你一个错误:

error FS1092: The type '<>f__AnonymousType0' is not accessible from this code location