DOT NET Interface Library v2

Aus expecco Wiki (Version 2.x)
Zur Navigation springen Zur Suche springen

Overview[Bearbeiten]

The .NET Interface Library (".NET Bridge") contains a mechanism to access Microsoft .NET (CLR) objects of a local or remote .NET application (a so-called .NET bridge), and an API for elementary blocks and a library of blocks to interact with these objects.

Programmatic Interface[Bearbeiten]

Access to .NET objects, classes and programs is done via a framework called "dotNET-Bridge". This framework implements transparent forwarding of expecco messages (virtual function calls) from either Smalltalk or JavaScript code to .NET objects as existent in a local or remote .NET virtual machine. Also, return values, callBacks and exception information are passed back from the .NET program to expecco. A proxy-object mechanism which catches all function calls, wraps the arguments and sends a datagram to the other bridge side is used for this to be almost completely transparent to the Smalltalk/JavaScript code inside expecco.

In addition to existing blocks of the .NET Interface Library, programmatic access to dotNET objects is sometimes useful or required. So the following information is useful if you want to write your own elementary .NET-blocks, or if you have to enhance the existing library by adding application-specific interface blocks.

Initializing / Releasing the Bridge[Bearbeiten]

Before any communication can take place between expecco and any dotNet object, the .NET side of the bridge has to be started, and a communication path to be setup. All of the bridges classes are in the DOTNET namespace; the main interface class is DotNet, in this namespace:

    dotNetHandle := DOTNET::DotNet newWithServer.

or (in JavaScript):

    dotNetHandle = DOTNET::DotNet.newWithServer();

This starts the .NET-side of the bridge (the executable named "DotNetBridge.Server.exe"), and waits for a connection request from this program.

When finished, release the bridge with:

    dotNetHandle.close();

which shuts down the connection and terminates the executable.

Loading Assemblies[Bearbeiten]

Using the "loadLibrary"-function, well-known assemblies can be loaded:

    dotNetHandle.loadLibrary("System.Windows.Forms");

or:

    dotNetHandle.loadLibrary("user32.dll");

Arbitrary files which contain assemblies are loaded with:

    dotNetHandle.loadFile(pathToDLL);

or:

    dotNetHandle.loadExtension(pathToDLL);

the former loads an assembly from the machine running the bridge server (DotNetBridge.Server.exe), the latter loads it from the machine running expecco. loadExtension also makes loaded assemblies available to dynamically compiled VB/C# compilation units.

Accessing Globals[Bearbeiten]

Globals, nameSpaces and members of a namespace are accessed using message sends to the dotNet handle, where the message name is the name of the global, namespace or interface. These messages can be chained, to access a hierarchy of namespaces. For example:

    dotNetHandle.System.Reflection.Assembly.LoadFile("c:\foo\bar\myAssembly.dll");

Instantiating a Class[Bearbeiten]

Object instances are created via the "new"-message, sent to a global:

    b = dotNetHandle.Button.new();
    f = dotNetHandle.Form.new();

once instantiated, any message can be sent transparently to such an .NET object, as if it was an expecco object:

    b.text("Hello World");
    f.controls.add(b);
    f.showDialog();

Initializing .NET Array Objects[Bearbeiten]

Only skalar types array "literals" (byte[], short[], float[], double[], long[], ...) are mapped directly to/from the corresponding Smalltalk array types (uint32[] <-> IntegerArray, int32[] <-> SignedIntegerArray, float[] <-> FloatArray, ....).

Arrays with non-literal elements have to be initialize explicitly. E.g. a String array is initilized the following way:

   "/ create a String Array with 20 elements.
   strArray := (bridge getDotNetType:'System.String[]') new:20.
   "/ initialize each element
   "/ NOTE! array index in .NET is 0-based!.
   strArray at:0 put:'Test0'.
   strArray at:1 put:'Test1'.
   strArray at:2 put:'Test2'.
   strArray at:19 put:'Test19'.

Callbacks[Bearbeiten]

Callbacks from .NET back into expecco are implemented via Smalltalk blocks (JavaScript anonymous functions). The bridge automatically installs an appropriate callback, whenever a block/function is given to a .NET component as a callback or hook.

Here is a complete example for creating a .NET form with a callback into expecco. This code could be put into an EB (Elementary Block) of an expecco activity diagram:

    var dotNet, form, button;

    // called when the .NET button is clicked
    function callBack() {
        dotNet.MessageBox.show("Hello from expecco");
    };

    dotNet = DOTNET::DotNet.newWithServer();
    dotNet.loadLibrary("System.Windows.Forms");

    button = dotNet.Button.new();
    button.text("Hello");
    button.click.add( callBack );

    form = dotNet.Form.new();
    button.dock( dotNet.DockStyle.fill );
    form.controls.add( button );

    form.showDialog();

    dotNet.close();

Remote Dynamic Code Injection[Bearbeiten]

C# and VB code can be dynamically loaded and compiled:

C#:

    typeCode := '
        using System;

        namespace SomeNamespace
        {
            class SomeClass
            {
                public static void ConsoleWrite(string text)
                {
                    Console.Write(text)
                }
            }
        }
    '.
    typeObject := dotnet getDotNetType:'SomeNamespace.SomeClass' fromCSharpSource:typeCode.
    typeObject ConsoleWrite:'Hello, World!'.

VB:


    moduleCode := '
        Imports System

        Namespace SomeNamespace
            Public Module SomeModule
                Sub ConsoleWrite(ByVal text As String)
                    Console.WriteLine (text)
                End Sub
            End Module
        End Namespace
    '.
    moduleObject := dotnet getDotNetType:'SomeNamespace.SomeModule' fromVBSource:moduleCode.
    moduleObject ConsoleWrite:'Hello, World!'.

Calling ActiveX/COM Objects[Bearbeiten]

It's possible to make calls to ActiveX/COM Objects through the bridge.

To do this, you need to create a dotNet Assembly with the types from a .tlb or .ocx file.

This can be done with the tlbimp utility which is part of VisualStudio (reachable through the VS Dev CMD Shell...)

In this shell, you can e.g. execute

tlbimp c:\windows\system32\wshom.ocx

which will create a file called IWshRuntimeLibrary.dll for the Windows Script Host Runtime Library in the current directory. This can then be used to automate the Windows Script Host Runtime Library Object.

Here an example how to use this in code:


    |dotNet shell buttonPressed|

    dotNet := DOTNET::DotNet newWithServer.
    dotNet loadFile:'C:\Temp\IWshRuntimeLibrary.dll'.
    shell := dotNet WshShellClass new.
    buttonPressed := shell popup:'Hello from Micha' secToWait:15 title:'.NET Bridge Com Demo' type:0.
    buttonPressed inspect


to be continued

See Also[Bearbeiten]

The Java Interface Plugin & Library, which implements a likewise interface for Java applications/libraries.


Back to Plugins
Back to Online Documentation.



Copyright © 2014-2024 eXept Software AG