tags:

views:

326

answers:

4

I have seen a demo of F# and DirectX.

User selects a part of F# code and sends it to F# interactive. It between, the form's thread is working: the form shows dynamic content and responds to clicks.

Can I conclude that for existing C# winforms project I can create a F# project which references it and then launch the F# project in F# interactive to run arbitrary methods of a form ?

EDIT: what are the steps to invoke btShowNextNumber_Click in a running application ?

public partial class Form1 : Form
{
    public Form1()
    {
        InitializeComponent();
    }

    int i = 0;

    private void btShowNextNumber_Click(object sender, EventArgs e)
    {
        ++i;
        label1.Text = i.ToString();
    }
}
+1  A: 

Sure, but you must follow CLS compliant rules. More info here: http://www.devarticles.com/c/a/C-Sharp/Making-Your-Code-CLS-Compliant/ http://msdn.microsoft.com/en-us/library/730f1wy3.aspx

Overdose
Thank you for the remark. Yes, the C# project is CLS-compliant.The actually 'wonder' I saw is that F# interactive keeps an `Application.Run()` running and invokes code in UI thread. I don't know how to do that currently.
modosansreves
+1  A: 

F# is just such CLR language as C# or VB are. This means that it may reference CLR assemblies (both DLLs and EXEs), import public classes from them and invoke public methods and properties. If class, method or property aren't public you can still access them using reflection, but there're few cases you really should do it.

Note that for WinForm UI elements to respond on user actions you'll need to run windows message loop (using Application.Run). In case of F# shell, it seems, they are running it in a background thread and post actions to this thread using Control.Invoke or its equivalents (WindowsFormsSynchronizationContext).

To invoke method you've shown in the sample you need do one of the following:

1) if method btShowNextNumber_Click is public:

form.Invoke(new Action(()=> form.btShowNextNumber_Click(form, EventArgs.Empty)));

or

SynchronizationContext.Current.Send(o => form.btShowNextNumber_Click(form, EventArgs.Empty));

2) if method btShowNextNumber_Click is not public, but Button btShowNextNumber is:

form.Invoke(new Action(()=> form.btShowNextNumber.PerformClick());

or

SynchronizationContext.Current.Send(o => form.btShowNextNumber.PerformClick());

As far as I understand the way F# shell works, it can be setted up post commands you post through SynchronizationContext.Send transparently, just like IronPython shell does. Can't say how exactly this works for now. Need to check

elder_george
Running the Application.Run() code in the background thread and invoking code on it is the feature I'm looking for.
modosansreves
Do you know how? Should I adapt the C# project? Yes, all the necessary methods are public, I just don't know what to send to F# interactive.
modosansreves
Thank you. I was also wandering how it's achieved underneath.
modosansreves
A: 

You need a debugger that supports managed code. It does not matter which language is used to write the host of your code. I debug my code in different containers like MS Office, IE, Windows Explorer, Visual Studio and other VB/C# apps all the time.

Sheng Jiang 蒋晟
+3  A: 

Sure. In F# interactive, you'd run something like:

#r "MyDllName.dll"
open MyNamespace

// Call the constructor to get a new form, then show it
let form = Form1()
form.Show()

// Call whatever public method you want
form.MyMethodThatIWantToUse()
kvb
Ah! I just noticed that breakpoints in C# project do not work this way. Any ideas to make them working?
modosansreves
Yep. Just found it. One has attach debugger to fsi.exe manually.
modosansreves