Генерация типов F # на основе предыдущего выбора типа - PullRequest
0 голосов
/ 28 октября 2018

Попытка создания новых типов на основе аргумента, предоставленного предыдущим типом.

Вот код фрагмент попытки:

Насколько я понимаю dimensionsType должен получить аргумент agencyId, переданный из здесь , который позже я использую для фильтрации значений до получения новых ProvidedProperty.

По какой-то причине agencyIdзначения в sizesType являются правильными, но в AddMembersDelayed анонимная функция значения не одинаковы. Вместо этого они поступают из collectionType : dimensionsType "WB" аргумент.

connection.Dataflows=> [
    // Id    Name                          AgencyId
    ("SDG", "SDG",                         "UNSD"),
    ("WDI", "World Development Indicators", "WB")
]


connection.Dimensions=> [
    //Id   AdgencyId
    ("WB", "FREQ"),
    ("WB", "SERIES"),
    ("WB", "REF_AREA"),
    ("UNSD", "FREQ111")
]




let dimensionsType agencyId =
    printfn "dimensionsType arg: [%s]" agencyId
    let someIntVal = 42            
    let someStrVal = "Str"            
    let t = ProvidedTypeDefinition("Dimensions", Some typeof<Dimensions>, hideObjectMethods = true, nonNullable = true)
    let fsn = fun aid () -> 
        [ for dimension in connection.Dimensions do
              printfn "dimension.agencyId [%s] - [%s] - [%s] - [%d] - [%s]" dimension.Id dimension.AgencyId aid someIntVal someStrVal
              if dimension.AgencyId = aid then
                  let prop = 
                      ProvidedProperty
                        ( dimension.Id, dimensionType, 
                          getterCode = (fun (Singleton arg) -> <@@ ((%%arg : Dimensions) :> IDimensions).GetDimension(dimension.EnumerationId) @@>))
                  if not (String.IsNullOrEmpty dimension.Position) then prop.AddXmlDoc(dimension.Position)
                  yield prop                     
        ]
    t.AddMembersDelayed (fsn agencyId)
    serviceTypesType.AddMember t
    t

let dataflowsType =
    let dataflowCollectionType = ProvidedTypeBuilder.MakeGenericType(typedefof<DataflowCollection<_>>, [ dimensionsType "WB"])
    let t = ProvidedTypeDefinition("Dataflows", Some dataflowCollectionType, hideObjectMethods = true, nonNullable = true)
    t.AddMembersDelayed (fun () ->
        [ for dataflow in connection.Dataflows do
            let prop =
                ProvidedProperty
                  ( dataflow.Name, dimensionsType dataflow.AgencyID,
                    getterCode = (fun (Singleton arg) -> <@@ ((%%arg : DataflowCollection<Dataflow>) :> IDataflowCollection).GetDataflow(dataflow.Id, dataflow.Name) @@>))
            prop.AddXmlDoc (sprintf "The data for dataflow '%s'" dataflow.Name)                
            yield prop])
    serviceTypesType.AddMember t
    t

Usage.fsx

#r @"../../../bin/lib/net45/FSharp.Data.dll"

open FSharp.Data
type SD = SdmxDataProvider<"https://api.worldbank.org/v2/sdmx/rest">
let wb = SD.GetDataContext()
let dataflows = wb.Dataflows // Output below is result of this line execution

Результат, которого я хочу достичь, - это создать разные свойства для двух следующих случаев:

wb.Dataflows.``World Development Indicators``. // based on ``World Development Indicators`` agencyId
wb.Dataflows.SDG // based on SDG agencyId

F # Интерактивный вывод

C                      #1          #2     #3     #4     #5
dimensionsType arg: [UNSD]
dimensionsType arg: [WB]
dimension.agencyId  [FREQ] -      [WB] - [WB] - [42] - [Str]
dimension.agencyId  [SERIES] -    [WB] - [WB] - [42] - [Str]
dimension.agencyId  [REF_AREA] -  [WB] - [WB] - [42] - [Str]
dimension.agencyId  [FREQ111] - [UNSD] - [WB] - [42] - [Str]
...