Page 1 of 1

CLR compiling - continuation section tricks

Posted: 27 Apr 2019, 12:07
by burque505
This script is in part a result of some back-and-forth with @sancarn and @evilC the threads at
this link, Topic: .NET Framework Interop (CLR, C#, VB), and some of this code is probably sancarn's or evilC's, or at least based on it.

First, this is NOT an attempt to show any 'right way' to do any .NET programming. I'm absolutely not the person to undertake that task.

The only real purpose of this is to show that you can dynamically alter C# or VB programs/scripts before compiling them via CLR.ahk.

Do this by preparing a 'template' script with a continuation section, using command-syntax, with variable references enclosed in '%[...]%' (%MyFirstString%, %MySecondString%, %MyThirdString% here), then dereference these values in another variable. This dereferencing pre-compilation keeps the CLR compiler from choking on the AHK variables. Here, the precompilation variable is 'presharp', and the variable to be compiled is 'csharp'. Not required. Code edited.

(There may be some useful program snippets in the code (I hope), primarily for inserting and removing items, but these aren't anything you can't find in two minutes with an online search, and they are not the motivation for this post.)

N.B. Obviously you don't have to limit yourself to just variables you'd use in your CLR language script - you could dynamically include entire scripts, individual methods, etc. This may make templating a bit easier.

Code: Select all

/* This script is in part a result of the threads at
https://www.autohotkey.com/boards/viewtopic.php?f=6&t=4633&p=220326&hilit=clr+arrays+burque505#p220326
(Topic: .NET Framework Interop (CLR, C#, VB)
First, this is NOT an attempt to show the 'right way' to do any .NET programming.

The only real purpose of this is to show that you can dynamically alter C#
or VB programs/scripts before compiling via CLR.ahk.

(There may be some useful program snippets in the code (I hope),
primarily for inserting and removing items, but these aren't anything
you can't find in two minutes with an online search, and they are not the reason for this script.)

Regards,
burque505
*/


#NoEnv  ; Recommended for performance and compatibility with future AutoHotkey releases.
; #Warn  ; Enable warnings to assist with detecting common errors.
SendMode Input  ; Recommended for new scripts due to its superior speed and reliability.
SetWorkingDir %A_ScriptDir%  ; Ensures a consistent starting directory.

gui, add, text, w200, Enter first pre-compilation variable
gui, add, edit, w300 y+5 vMyFirstString
gui, add, text, y+5 w200, Enter second pre-compilation variable
gui, add, edit, w300 y+5 vMySecondString
gui, add, text, y+5 w200, Enter third pre-compilation variable
gui, add, edit, w300 y+5 vMyThirdString
gui, add, text, y+5 w250, The following variables will be used post-compile
gui, add, text, y+10 w200, Enter variable for key "4"
gui, add, edit, w300 y+5 vAdd4
gui, add, text, y+10 w200, Enter variable for key "5"
gui, add, edit, w300 y+5 vAdd5
gui, add, text, y+10 w200, Enter variable to insert at index 5
gui, add, edit, w300 y+5 vAddInsert
gui, add, Button, y+5 Default, Submit
gui show, w350 h330, Dynamic compilation test

return

ButtonSubmit:
Gui, submit

csharp =

(
using System.Collections.Generic;
using System.Windows.Forms;

class Foo
{
    private List<KeyValuePair<int, string>> list = new List<KeyValuePair<int, string>>();
    public void Create()
    {
        // Create List of key-value pairs.

        list.Add(new KeyValuePair<int, string>(1, "%MyFirstString%"));
        list.Add(new KeyValuePair<int, string>(2, "%MySecondString%"));
        list.Add(new KeyValuePair<int, string>(3, "%MyThirdString%"));
        // These AHK variables will be expanded before compilation.

        // Loop over pairs.
        foreach (KeyValuePair<int, string> pair in list)
        {
            // Get key.
            int key = pair.Key;
            // Get value.
            string value = pair.Value;
            // Display.
            MessageBox.Show(key.ToString() + " " + value.ToString());
        }
    }

    public void Add(int key, string val)
    {
        list.Add(new KeyValuePair<int, string>(key, val));
    }

    public void Insert(int index, int key, string val)
    {
        list.Insert(index, new KeyValuePair<int, string>(key, val));
    }

    public void RemoveAt(int index)
    {
        list.RemoveAt(index);
    }
    
        public void Remove(int key, string val)
    {
        list.Remove(new KeyValuePair<int, string>(key, val));
    }


    public void Show()
    {
        string myString = "";
        foreach (KeyValuePair<int, string> pair in list)
        {
            // Get key.
            int key = pair.Key;
            // Get value.
            string value = pair.Value;
            // Display.
            myString += pair.Value + " ";
        }
        // Display.
        MessageBox.Show(myString);
    }
}

)


msgbox %csharp% 
/*  Uncomment the line above if you want to be sure
    that the variables are actually being expanded.
*/

asm := CLR_CompileC#(csharp,"System.dll|System.Windows.Forms.dll|System.Collections.dll")
obj := CLR_CreateObject(asm,"Foo")
; First create a list of k/v pairs with some members initialized
obj.Create()
; Add a couple of key-value pairs
obj.Add(4, Add4)
obj.Add(5, Add5)
; Now, convert the values to a string and display.
obj.Show()
; list.Insert() takes (int, int, string)
obj.Insert(5, 6, AddInsert)
obj.Show()
; list.RemoveAt operates on the index, NOT the key,
; so this will remove the fifth element of the
; list, NOT the fourth (zero-based index).
obj.Remove(6, AddInsert)
obj.Show()
obj.RemoveAt(4)
obj.Show()

ExitApp

Escape::
guiclose:
ExitApp

Regards,
burque505
DynaComp.gif
DynaComp.gif (370.49 KiB) Viewed 510 times

Re: CLR compiling - continuation section tricks

Posted: 29 Apr 2019, 04:23
by evilC
"The only real purpose of this is to show that you can dynamically alter C# or VB programs/scripts before compiling them"
Sorry, not seeing how this code does that - it just seems to create a collection and add some values to it.
Am I missing something?

Code: Select all

asm := CLR_CompileC#(csharp,"System.dll|System.Windows.Forms.dll|System.Collections.dll")
obj := CLR_CreateObject(asm,"Foo")
; First create a list of k/v pairs with some members initialized
obj.Create()
; Add a couple of key-value pairs
obj.Add(4, Add4)

Re: CLR compiling - continuation section tricks

Posted: 29 Apr 2019, 08:08
by burque505
@evilC, in the OP the variables are expanded before compilation ("dynamically" - whether rightly or wrongly - referring to the fact that they were obtained from the GUI and not declared statically within the code) and variables are also added after compilation.

Code: Select all

        list.Add(new KeyValuePair<int, string>(1, "%MyFirstString%"));
        list.Add(new KeyValuePair<int, string>(2, "%MySecondString%"));
        list.Add(new KeyValuePair<int, string>(3, "%MyThirdString%"));
        // These AHK variables will be expanded before compilation.
In the code snippet you show, values are also being added afterwards. (Now in this particular case, granted, I could just add values afterwards - that's not always easy or even possible, especially with many 3rd-party .NET dlls.)

The value of the exercise to me is that I can now more easily deal with .NET dlls that don't lend themselves to creation with 'Clr_LoadLibrary' and manipulation following 'Clr_CreateObject', in AHK alone, without compiling any more C#. In the next day or so I'll be posting a find-and-replace script for .docx files, using DocX.dll, where I've had to use exactly the approach outlined above.

Re: CLR compiling - continuation section tricks

Posted: 29 Apr 2019, 10:36
by evilC
Ohhhh I get it, "%MyFirstString%" is not opening a string, specifying a variable, then closing the string, it's closing the string, specifying a variable, then opening the string again
Apologies...

Re: CLR compiling - continuation section tricks

Posted: 29 Apr 2019, 10:49
by burque505
No apologies needed :)
I appreciate your interest, as always.
Regards,
burque505

Re: CLR compiling - continuation section tricks

Posted: 02 Jun 2019, 07:04
by sancarn
Cool stuff. IIRC you should use @"%var%" because I think the @ makes it a heredoc. See this example. This way it can easily deal with new lines and stuff :)