我希望使用F#WSDL Type Provider。要调用我正在使用的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>
还是应该使用原始OfType<T>
?
答案 0 :(得分:5)
我想这个问题主要是关于break
构造,这在F#中是不可用的。好吧,代码实际上只是为集合的第一个元素设置用户名和密码(如果集合为空,则为none)。如果您将集合转换为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
| _ -> ()
答案 1 :(得分: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