Лучший способ определить тип переменной и обращаться с каждым по-разному в F # - PullRequest
1 голос
/ 12 мая 2010

У меня есть функция, которая создает предложение select where, но сейчас все должно быть строкой.

Я хотел бы взглянуть на переданную переменную и определить ее тип, а затем обработать ее правильно.

Например, числовые значения не имеют одинарных кавычек, тип параметра будет либо нулевым, либо имеет какое-либо значение, а логическое значение будет фактически равным нулю или единице.

member self.BuildSelectWhereQuery (oldUser:'a)  =  //'
    let properties = List.zip oldUser.ToSqlValuesList sqlColumnList 
    let init = false, new StringBuilder()
    let anyChange, (formatted:StringBuilder) = 
        properties |> Seq.fold (fun (anyChange, sb) (oldVal, name) ->
            match(anyChange) with
            | true -> true, sb.AppendFormat(" AND {0} = '{1}'", name, oldVal)
            | _ -> true, sb.AppendFormat("{0} = '{1}'", name, oldVal)
        ) init
    formatted.ToString()

Вот одна сущность:

type CityType() =
    inherit BaseType()
    let mutable name = ""
    let mutable stateId = 0
    member this.Name with get() = name and set restnameval=name <- restnameval
    member this.StateId with get() = stateId and set stateidval=stateId <- stateidval
    override this.ToSqlValuesList = [this.Name; this.StateId.ToString()]

Итак, если name было каким-то другим значением, кроме строки, или stateId может быть необязательным, то я должен сделать два изменения:

  1. Как мне изменить ToSqlValuesList на есть переменная, чтобы я мог сказать тип переменной?
  2. Как мне изменить мою функцию выбора справиться с этим?

Я думаю, что мне нужна новая функция, которая выполняет обработку, но какой лучший способ FP сделать это, вместо того, чтобы использовать что-то вроде typeof?

Ответы [ 2 ]

3 голосов
/ 13 мая 2010

Вы можете использовать тестовый шаблон типа в совпадении. Будет ли это соответствовать вашим потребностям?

let f (x : obj) =
    match x with
    | :? int -> "int"
    | :? string -> "string"
    | :? bool -> "bool"
    | _ -> "who knows?"
2 голосов
/ 12 мая 2010

Я думаю, что одним из четких функциональных подходов было бы определение типа данных, представляющих различные (более сложные ситуации), с которыми вам нужно справиться. Вы упомянули, что значение может быть необязательным, и вам необходимо различать числовые и текстовые значения (для кодирования в SQL).

Вы можете определить дискриминационное объединение (если есть другие случаи, которые вы хотели бы обработать, определение может быть немного более сложным):

type SqlValue = 
  | Missing
  | Numeric of string
  | Textual of string

Обратите внимание, что в случае Textual также содержится string, потому что я предполагаю, что клиент, который производит значение, заботится о преобразовании его в строку - это только информация для вашего генератора SQL-запросов (чтобы он знал, является ли он нужно добавить цитаты).

Ваш элемент ToSqlValuesList вернет список значений string & SqlValue, поэтому, например, образец продукта может быть представлен в следующем списке:

columns = [ "Name"; "Price"; "Description" ]
values = [ Textual("Tea"); Numeric(10); Missing ]

В коде, который генерирует запрос SQL, вы будете использовать сопоставление с шаблоном для обработки всех различных случаев (что наиболее важно, кодируйте строку, чтобы избежать внедрения SQL в случае, если значение равно Textual: -)).

РЕДАКТИРОВАТЬ Вам потребуется реализовать преобразование из определенных типов данных в представление SqlValue в каждом клиенте. Однако это можно упростить, написав тип утилиты (используя тот факт, что члены могут быть перегружены):

type SqlValue with 
  static member From(a:int) = Numeric(a.ToString())
  static member From(a:int option) = 
    match a with None -> Missing | Some(n) -> SqlValue.From(n)
  // ... similarly for other types

В реализации ToSqlValuesList вы должны написать SqlValue.From(description), и он будет автоматически обрабатывать детали.

Более сложным подходом было бы аннотировать открытые члены типов, представляющих ваши сущности данных, с помощью атрибутов .NET и использовать Reflection для извлечения значений (и их типов) во время выполнения. Это более продвинутый, но довольно элегантный (хороший пример этой техники в книге F # Дона Сайма «Эксперт»)

...