2

我正在寻找使用 F# WSDL 类型提供程序。要调用我正在使用的 Web 服务,我需要将我的客户端凭据附加到System.ServiceModel.Description.ClientCredentials.

这是我拥有的 C# 代码:

var serviceClient = new InvestmentServiceV1Client.InvestmentServiceV1Client();

foreach (ClientCredentials behaviour in serviceClient.Endpoint.Behaviors.OfType<ClientCredentials>())
{
    (behaviour).UserName.UserName = USERNAME;
    (behaviour).UserName.Password = PASSWORD;
    break;
}

这是我到目前为止的 F# 代码:

let client = new service.ServiceTypes.InvestmentServiceV1Client()
let xxx = client.Endpoint.Behaviors
|> Seq.choose (fun p -> 
    match box p with   
    :?   System.ServiceModel.Description.ClientCredentials as x -> Some(x) 
    _ -> None) 
|> (System.ServiceModel.Description.ClientCredentials)p.UserName.UserName = USERNAME

是否有 F# 等价物System.Linq.Enumerable.OfType<T>或者我应该只使用 raw OfType<T>

4

2 回答 2

5

我想问题主要是关于break构造,它在 F# 中不可用。好吧,代码实际上只是为集合的第一个元素设置了用户名和密码(如果集合为空,则没有)。如果将集合转换为 F# 列表,则可以使用模式匹配轻松完成此操作:

// Get behaviours as in C# and convert them to list using 'List.ofSeq'
let sc = new InvestmentServiceV1Client.InvestmentServiceV1Client()
let behaviours = sc.Endpoint.Behaviors.OfType<ClientCredentials>() |> List.ofSeq

// Now we can use pattern matching to see if there is something in the list
match behaviours with
| behaviour::_ ->
    // And if the list is non-empty, set the user name and password
    behaviour.UserName.UserName <- USERNAME
    behaviour.UserName.Password <- PASSWORD
| _ -> ()
于 2013-10-14T08:45:33.307 回答
4

我认为您已经实现了.OfType()的 F# 等效项。为了模拟break语句,您可以像 Tomas 在他的回答中所做的那样(匹配列表),或者调用Seq.head(如果没有剩余元素则抛出),或者您可以这样做:

let xxx = 
    client.Endpoint.Behaviors
    |> Seq.choose (function
        | :? System.ServiceModel.Description.ClientCredentials as x -> Some x
        | _ -> None ) 
    |> Seq.tryPick Some

match xxx with
| Some behavior -> ... // First element of required type found
| None -> ...          // No elements of required type at all in sequence
于 2013-10-14T11:29:11.700 回答