Our team provides a metro spreadsheet application with portable library. The new F# 3.0 does support portable library which is currently a way to write Win8 app using F#. The portable library hosts all the logic and the UI logic is still in the application, which is a clean cut for the F# library and front-end UI.
Sunday, April 29, 2012
Monday, April 23, 2012
A Trick in F# Interop
When I try to crack the .CAB file, I found the COM interop in F# is different from C#.
the code sample in C# like the following code after adding "Microsoft Shell Controls And Automation" from "COM" tab.
It should be straightforward to transform from this C# to F#. But it turns out the Shell cannot be created because it is an interface! Yes, you are not reading a typo. Shell is a interface if you use the Object Viewer.
The C# side can pick up the CoClass attribute so the new statement is calling into the ShellClass. Actually you cannot new ShellClass in C# code.
[CoClass(typeof(ShellClass))]
[Guid("866738B9-6CF2-4DE8-8767-F794EBE74F4E")]
public interface Shell : IShellDispatch5
{
}
In F# side, you have to create ShellClass instead of Shell. So if you want to convert C# code which involves COM component to F# code, try to find the real class by finding the CoClass attribute. The complete F# code is listed below:
let shell = new ShellClass()
let folder = shell.NameSpace(Path.GetDirectoryName(fn))
let fileName = Path.GetFileName(fn)
let currentFolder =
if not (Directory.Exists currentFolder) then
Directory.CreateDirectory currentFolder |> ignore
for item in shell.NameSpace(fn).Items() do
folder.CopyHere(item, 0)
the code sample in C# like the following code after adding "Microsoft Shell Controls And Automation" from "COM" tab.
bool ExpandCabFile(string CabFile, string DestDir)
{
if (!Directory.Exists(DestDir)) return false;
Shell sh = new Shell();
Folder fldr = sh.NameSpace(DestDir);
foreach (FolderItem f in sh.NameSpace(CabFile).Items()) fldr.CopyHere(f, 0);
return true;
}
It should be straightforward to transform from this C# to F#. But it turns out the Shell cannot be created because it is an interface! Yes, you are not reading a typo. Shell is a interface if you use the Object Viewer.
The C# side can pick up the CoClass attribute so the new statement is calling into the ShellClass. Actually you cannot new ShellClass in C# code.
[CoClass(typeof(ShellClass))]
[Guid("866738B9-6CF2-4DE8-8767-F794EBE74F4E")]
public interface Shell : IShellDispatch5
{
}
In F# side, you have to create ShellClass instead of Shell. So if you want to convert C# code which involves COM component to F# code, try to find the real class by finding the CoClass attribute. The complete F# code is listed below:
let shell = new ShellClass()
let folder = shell.NameSpace(Path.GetDirectoryName(fn))
let fileName = Path.GetFileName(fn)
let currentFolder =
if not (Directory.Exists currentFolder) then
Directory.CreateDirectory currentFolder |> ignore
for item in shell.NameSpace(fn).Items() do
folder.CopyHere(item, 0)
Saturday, April 21, 2012
Self Note: Word 2010 field
As my book is adding more and more listings, figures, and tables. It was so bad that I cannot use cross-reference because of the template restriction. I am forced to find a way to define something can increase automatically and can be referenced.
OK, first define something to automatically increase. The "seq" field is what I chose. SEQ chapter1List is used to define a list sequence.
Secondly, I need to find a way to do reference. I select the text needs to be referenced and set it as a Bookmark. When the cross-reference can work.
Word fields are not updated automatically. Use Ctrl+A to select all and F9 is the way to update all fields.
Thursday, April 19, 2012
XML document on F# primary constructor
XML document on primary constructor is
not supported. The workaround is to define another constructor with a dummy
parameter. See the following sample code
/// my xml doc
type A(args) =
// change to the following code with a dummy parameter
type A private(args, _dummyParameter:unit) =
/// docs
new(args) = A(args, ())
type A(args) =
// change to the following code with a dummy parameter
type A private(args, _dummyParameter:unit) =
/// docs
new(args) = A(args, ())
Friday, April 13, 2012
Execution of Static Initializers
I have been struggling with the following code for days. Now it is clear that it is by design.
If you create a project with two files, one is File1.fs and the other is Program.fs. Put the following code in the File1.fs
If you create a project with two files, one is File1.fs and the other is Program.fs. Put the following code in the File1.fs
namespace BB
// define a Point2D class with parameterized primary contructor
type Point2D(xValue:double, yValue:double) =
// define a static field named count
static let mutable count = 0
type Screen() =
let points = System.Collections.Generic.List < Point2D > ()
member this.Item with get(x:int) = points.[x]
and set(x:int) (v) = points.[x] <- v
module TestModule =
let screen = Screen()
let r2 = screen.[0]
and create the Point2D class in Program.fs.
let a = BB.Point2D()
When you run it you are going to bump into an exception about TypeInitializationException. OK, please move your staring eyes down to the TestModule, even it is 300 lines down below. screen.[0] is access a non-existing element.
Reason? the spec will you everything. http://research.microsoft.com/en-us/um/cambridge/projects/fsharp/manual/spec.html#_Toc270597617
Do if a static variable is initialized, the module is also executed. So next time when you see this wired error, you need to look around OR open the inner exception's call stack information.
Thursday, April 12, 2012
Auto-Implement Property and Constructor do binding in Beta
From the previous F# auto-implemented property post, that property declaration shortcut does provide convenience to developer. However, when it combines with the constructor, there are something interesting.
type A() as this =
do this.Bar()
// let Y@ = 0
member this.Bar() = printfn "In F()"
//member val Y = 0 with get,set
let a = new A()
The code above works. But when you uncomment the auto-implemented property. The code compiles but will spite out an error at the printfn.
type A() as this =
do this.Bar()
// let Y@ = 0
member this.Bar() = printfn "aaa" //error!
member val Y = 0 with get,set
let a = new A()
System.InvalidOperationException occurred
HResult=-2146233079
Message=The initialization of an object or value resulted in an object or value being accessed recursively before it was fully initialized.
Source=FSharp.Core
StackTrace:
at Microsoft.FSharp.Core.LanguagePrimitives.IntrinsicFunctions.FailInit()
InnerException:
I was confused by the error message at first glance. where is the object or value needs to be initialized? Actually this error says the A class cannot be initialized. If you want to ask why?
The auto-implemented property put a hidden backend field right after the do binding section. The commented out line after the do this.Bar() is the hidden code. As a result, when do binding is trying to execute this.Bar(), there is still one field, Y@, needs to be initialized. Because one of the fields needs to be initialized, the instance is not initialized. That's how you get this error.
This exists in Beta. So if you run into this problem, do not panic. you can try to use the old way to define the property.
This exists in Beta. So if you run into this problem, do not panic. you can try to use the old way to define the property.
Subscribe to:
Posts (Atom)