首页 文章

F#ExpandoObject as Dictionary

提问于
浏览
1

在工作缓慢的时候,我想将一个我用C#编写的小数据库访问框架转换为F# . 该框架广泛使用动态和ExpandoObjects . 特别是,这一点令我头疼:

public static List<dynamic> ToDynamic(this IDataReader reader)
{
    dynamic result = new List<dynamic>();

    while (reader.Read())
    {
        var item = new ExpandoObject();
        var dc = item as IDictionary<String, object>;
        for (int i = 0; i < reader.FieldCount; i++)
        {
            dc.Add(reader.GetName(i), DBNull.Value.Equals(reader[i]) ? null : reader[i]);
        }

        result.Add(item);
    }

    return result;
}

你怎么把它翻译成F#?这就是我能想到的:

let (~~) (x:obj) = 
    match x with
    | :? 't as t -> t 
    | _ -> null

let rec mapper (reader : SqlDataReader) : list<'Value> =
    match reader.Read() with
    | false -> []
    | true ->
        let dc = new ExpandoObject()
        let dictionary = ~~dc : Dictionary<string, obj>
        [for i in [0 .. reader.FieldCount - 1] do
            dictionary.Add(reader.GetName(i), reader.GetValue(i))] @ mapper reader

当然,除了字典在循环中出现空值 . ~~ 应该用C#替换 as 运算符,但我想事情并不那么简单 . 这可能只是星期五的情况,但我真的看不清楚这一点 .

1 回答

  • 2

    由于动态没有语言支持,因此F#中涉及的内容稍微多一些 . (我建议阅读DynamicAttribute上的文档 . )这是一个翻译:

    open System.Collections.Generic
    open System.Data
    open System.Dynamic
    open System.Runtime.CompilerServices
    
    [<CompiledName("ToDynamic")>]
    let toDynamic (reader: IDataReader) : [<return: Dynamic([|false;true|])>] ResizeArray<obj> = 
      let results = ResizeArray<obj>()
      let rec loop() =
        if reader.Read() then
          let obj = ExpandoObject() :> IDictionary<_,_>
          for i = 0 to reader.FieldCount - 1 do
            obj.Add(reader.GetName(i), if reader.IsDBNull(i) then null else reader.[i])
          results.Add(obj)
          loop()
        else results
      loop()
    

    如果您只想动态访问 IDataReader 中的值,F#中更优雅的解决方案是重载动态运算符:

    let (?) (reader: IDataReader) (name: string) = 
      match reader.[name] with
      | :? DBNull -> Unchecked.defaultof<_>
      | value -> unbox value
    
    //Usage: reader?Id
    

相关问题