Skip to content

Latest commit

 

History

History
67 lines (57 loc) · 2.98 KB

dynamic-invoke.md

File metadata and controls

67 lines (57 loc) · 2.98 KB

Dynamically invoke .NET APIs from JavaScript

For examples of this scenario, see ../examples/dynamic-invoke/ or ../examples/semantic-kernel/.

  1. Add a dependency on the node-api-dotnet npm package to your JavaScript project:

    npm install node-api-dotnet
    
  2. Import the node-api-dotnet package in your JavaScript code:

    const dotnet = require('node-api-dotnet');

    Or if using ES modules:

    import dotnet from 'node-api-dotnet';
  3. Load a .NET assembly from its path:

    const ExampleAssembly = dotnet.load('path/to/ExampleAssembly.dll');

    If the assembly depends on other non-framework assemblies, set up a resolving event handler before loading the target assembly:

    dotnet.addListener('resolving', (name, version) => {
        const filePath = path.join(__dirname, 'bin', name + '.dll');
        if (fs.existsSync(filePath)) dotnet.load(filePath);
    });
  4. Types in the assembly are projected as properties on the loaded assembly object. So then you can use those to call static methods, construct instances of classes, etc:

    ExampleAssembly.StaticClass.ExampleMethod();
    const exampleObj = new ExampleAssembly.ExampleClass(...args);

    Of course you can access properites, pass arguments to methods, get return values, and so on. Most types get automatically marshalled between JavaScript and .NET as you'd expect. For details, see the type projections reference.

    ⚠️ Generic types and methods are not yet supported very well -- with the exception of generic collections which work great.

  5. Optional: Use the node-api-dotnet-generator tool to generate type definitions for the assembly:

    npm exec node-api-dotnet-generator -- -typedefs ExampleAssembly.d.ts --assembly path/to/ExampleAssembly.dll --reference path/to/DependencyAssembly.dll
    

    ⚠️ Any dependencies need to be explicitly referenced with the --reference option.

    ⚠️ You may see some warnings about types like Span<T> that are not (yet) supported for projecting to JavaScript. The warnings can be ignored if you don't plan on using those specific APIs.

    After generating the type definitions file, import it as a TypeScript type annotation comment:

    /** @type import('./ExampleAssembly') */
    const ExampleAssembly = dotnet.load('path/to/ExampleAssembly.dll');

    Then you'll notice your IDE offers documentation-comments and member completion from the type definitions, and the TypeScript compiler will use the type definitions.

  6. Optional: Wrap up the loading code in a convenient JavaScript module that exports the assembly with type definitions. For an example of this, see ../examples/semantic-kernel/semantic-kernel.js