Я новичок в F # и SL и играю с получением асинхронного HttpResponse через Silverlight.Ниже приведены фрагменты кода F #, которые протестированы на VS2010 и Window7 и работают хорошо, но необходимо улучшить.Любые советы и обсуждения, особенно часть callback , приветствуются и большое спасибо.
module JSONExample
open System
open System.IO
open System.Net
open System.Text
open System.Web
open System.Security.Authentication
open System.Runtime.Serialization
[<DataContract>]
type Result<'TResult> = {
[<field: DataMember(Name="code") >]
Code:string
[<field: DataMember(Name="result") >]
Result:'TResult array
[<field: DataMember(Name="message") >]
Message:string
}
// The elements in the list
[<DataContract>]
type ChemicalElement = {
[<field: DataMember(Name="name") >]
Name:string
[<field: DataMember(Name="boiling_point") >]
BoilingPoint:string
[<field: DataMember(Name="atomic_mass") >]
AtomicMass:string
}
//http://blogs.msdn.com/b/dsyme/archive/2007/10/11/introducing-f-asynchronous-workflows.aspx
//http://lorgonblog.spaces.live.com/blog/cns!701679AD17B6D310!194.entry
type System.Net.HttpWebRequest with
member x.GetResponseAsync() =
Async.FromBeginEnd(x.BeginGetResponse, x.EndGetResponse)
type RequestState () =
let mutable request : WebRequest = null
let mutable response : WebResponse = null
let mutable responseStream : Stream = null
member this.Request with get() = request and set v = request <- v
member this.Response with get() = response and set v = response <- v
member this.ResponseStream with get() = responseStream and set v = responseStream <- v
let allDone = new System.Threading.ManualResetEvent(false)
let getHttpWebRequest (query:string) =
let query = query.Replace("'","\"")
let queryUrl = sprintf "http://api.freebase.com/api/service/mqlread?query=%s" "{\"query\":"+query+"}"
let request : HttpWebRequest = downcast WebRequest.Create(queryUrl)
request.Method <- "GET"
request.ContentType <- "application/x-www-form-urlencoded"
request
let GetAsynResp (request : HttpWebRequest) (callback: AsyncCallback) =
let myRequestState = new RequestState()
myRequestState.Request <- request
let asyncResult = request.BeginGetResponse(callback, myRequestState)
()
// easy way to get it to run syncrnously w/ the asynch methods
let GetSynResp (request : HttpWebRequest) : HttpWebResponse =
let response = request.GetResponseAsync() |> Async.RunSynchronously
downcast response
let RespCallback (finish: Stream -> _) (asynchronousResult : IAsyncResult) =
try
let myRequestState : RequestState = downcast asynchronousResult.AsyncState
let myWebRequest1 : WebRequest = myRequestState.Request
myRequestState.Response <- myWebRequest1.EndGetResponse(asynchronousResult)
let responseStream = myRequestState.Response.GetResponseStream()
myRequestState.ResponseStream <- responseStream
finish responseStream
myRequestState.Response.Close()
()
with
| :? WebException as e
-> printfn "WebException raised!"
printfn "\n%s" e.Message
printfn "\n%s" (e.Status.ToString())
()
| _ as e
-> printfn "Exception raised!"
printfn "Source : %s" e.Source
printfn "Message : %s" e.Message
()
let printResults (stream: Stream)=
let result =
try
use reader = new StreamReader(stream)
reader.ReadToEnd();
finally
()
let data = Encoding.Unicode.GetBytes(result);
let stream = new MemoryStream()
stream.Write(data, 0, data.Length);
stream.Position <- 0L
let JsonSerializer = Json.DataContractJsonSerializer(typeof<Result<ChemicalElement>>)
let result = JsonSerializer.ReadObject(stream) :?> Result<ChemicalElement>
if result.Code<>"/api/status/ok" then
raise (InvalidOperationException(result.Message))
else
result.Result |> Array.iter(fun element->printfn "%A" element)
let test =
// Call Query (w/ generics telling it you wand an array of ChemicalElement back, the query string is wackyJSON too –I didn’t build it don’t ask me!
let request = getHttpWebRequest "[{'type':'/chemistry/chemical_element','name':null,'boiling_point':null,'atomic_mass':null}]"
//let response = GetSynResp request
let response = GetAsynResp request (AsyncCallback (RespCallback printResults))
()
ignore(test)
System.Console.ReadLine() |> ignore