I bought a bunch of SharePoint 2010 books and haven't had the time to go through those books. Recently, I finally had some time to take look at those books and try it out in F#. Trying out examples with SharePoint 2007 was fairly painless as I get to do everything in a 32-bit environment. Trying to get Visual Studio 2010 F# to work with SharePoint 2010 was more challenging. While I was able to get the compiled F# code to work, I couldn't overcome the hurdles to get SharePoint 2010 to work with F# Interactive, which is really my prefer way to investigate SharePoint server object models. I can tell from this Stack Overflow entry that I was not alone in having trouble to get F# interactive to work with SharePoint API. The combination of .NET 3.5 framework and 64-bit defeated my effort at getting it to work. I have tried Igor Dvorkin's steps to run F# interactive in 64-bit and then taking the command line arguments for the F# compiler and apply to F# interactive where applicable. So I would start up my F# interactive with the following command line parameters:
"C:\Program Files (x86)\Microsoft F#\v4.0\fsi.exe" ^ --debug:full ^ --noframework ^ --define:DEBUG ^ --define:TRACE ^ --optimize- ^ --tailcalls- ^ -r:"C:\Program Files (x86)\Reference Assemblies\Microsoft\FSharp\2.0\Runtime\v2.0\FSharp.Core.dll" ^ -r:"C:\Program Files\Common Files\Microsoft Shared\Web Server Extensions\14\ISAPI\Microsoft.SharePoint.dll" ^ -r:C:\Windows\Microsoft.NET\Framework\v2.0.50727\mscorlib.dll ^ -r:"C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\v3.5\System.Core.dll" ^ -r:C:\Windows\Microsoft.NET\Framework\v2.0.50727\System.dll ^ -r:"C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\v3.0\System.ServiceModel.dll"
When I try to run with the above arguments, I get the following error:
error FS0084: Assembly reference 'C:\Program Files (x86)\Reference Assemblies\Microsoft\FSharp\2.0\Runtime\v2.0\FSharp.Compiler.Interactive.Settings.dll' was not found or is invalid
So something in FSharp.Compiler.Interactive.Settings.dll
is not working with .NET Framework 3.5. I wish there was an option in F# interactive that allows me to target the runtime .NET framework to use (e.g. --target:3.5)
The good news is that the F# compiler works fine as long as you make sure that you are targeting .NET 3.5 runtime and x64 CPU. Here's the F# version of a sample code that I pulled from the book Inside Microsoft SharePoint 2010 by Ted Pattison, Andrew Connell, Scott Hillier and David Mann
open System open Microsoft.SharePoint let siteUrl = "http://localhost/" let sites = new SPSite(siteUrl) let site = sites.RootWeb http://www.blogger.com/blogger.g?blogID=18281936#editor/target=post;postID=3313071912798963533 seq {for i in 0..(site.Lists.Count-1) do if site.Lists.[i].Hidden <> true then yield (site.Lists.[i]) } |> Seq.iter (fun item -> printf "%s\n" item.Title)
For those who have read my past posts on F# and SharePoint and my past blog post on Revisiting the SharePoint collection adapter for F#, I am sorry to say that I have been led astray by C# example codes and my brain temporary malfunctioned as it produced the SharePoint adapter nonsense in that previous blog post. There was no need to write any SharePoint utility library in C# to get F# to work with SPListCollection as sequences. In the above example, I used sequence expressions to generate SPList sequences from SPListCollection. Another way is to simply create a sequence by use map function as shown in the following example:
// Create a sequence by mapping over all items in the collection let spcollection = site.Lists [0..spcollection.Count-1] |> Seq.map (fun i -> spcollection.[i]) |> Seq.iter (fun item -> printf "%s\n" item.Title)
There was no need to leave the confines of F# development and it is also type safe compared to my previous clumsy attempt at converting SPListCollection
into a sequence. If you really do want to use an adapter, it could also be implemented in F# as follows:
// SPCollectionAdapter written in F# let fromSPCollection<'a,'b when 'b :> SPBaseCollection> (collection:'b) = let enumerator = collection.GetEnumerator() let rec enumerate (e:Collections.IEnumerator) acc = let flag = e.MoveNext() if flag = false then acc else enumerate e (e.Current :?> 'a :: acc) enumerate enumerator [] // Example usages fromSPCollection<SPList,SPListCollection> site.Lists |> Seq.iter (fun item -> printf "%s\n" item.Title) // webapp is an instance of SPWebApplication object fromSPCollection<SPContentDatabase,SPContentDatabaseCollection> webapp.ContentDatabases |> Seq.iter (fun db -> printf "Content Database : %s\n" db.Name printf "Connection String : %s\n" db.DatabaseConnectionString)
No comments:
Post a Comment