Один из способов сделать это - определить список соответствующих «получателей» (функций, которые принимают одну из ваших записей и возвращают строку) для каждого из полей вместе с соответствующей ошибкой.Для простоты я сделал alternateAddress
необязательным:
let comparers : ((Address -> _) * (AlternateAddress -> _) * _) list =
[ (fun x -> x.Street), (fun x -> x.Street), InvalidStreet;
(fun x -> x.City), (fun x -> x.City), InvalidStreet
(fun x -> x.Region), (fun x -> x.Region), InvalidStreet
(fun x -> x.PostalCode), (fun x -> x.PostalCode), InvalidStreet
(fun x -> x.Country), (fun x -> x.Country), InvalidStreet ]
Теперь вы можете перебрать comparers
и использовать первую функцию для получения поля из Address
, вторую функцию для получения поляиз AlternateAddress
и, если они не совпадают, возвращают третий элемент кортежа, который является ошибкой для сообщения.
Вы можете использовать List.choose
, чтобы получить список, который пуст, когда все поля совпадают ив противном случае содержит список ошибок при наличии несовпадающих полей:
let errors = comparers |> List.choose (fun (getAddr, getAlt, err) ->
if getAddr address != getAlt alternateAddress then Some err else None)
Список errors
будет пустым, если проблем нет, будет содержать одну ошибку, если была только одна ошибка, или содержать несколько ошибок.:
match errors with
| [] -> printfn "All good!"
| [err] -> printfn "One error: %A" err
| _ -> printfn "Multiple errors!"
Стоит отметить, что в зависимости от вашей конкретной ситуации, возможно, будет хорошей идеей реструктурировать код, чтобы упростить эту операцию - но сложно сказать, не зная больше о вашей ситуации.