npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2024 – Pkg Stats / Ryan Hefner

@kwruntime/typedotnet

v0.1.9

Published

Run CSharp code, and access to any type/object in .NET 6 and .NET Framework/Mono

Downloads

41

Readme

Typedotnet

Run CSharp code, and access to any type/object in .NET 6 and .NET Framework/Mono

Supports (no tested on Mac but should work):

  • .NET 6 or superior (called before .NET Core), on Windows/Linux/Mac
  • .NET Framework 4.5 or superior on Windows
  • Mono on Linux/Mac

Build module

This module was created using @kwruntime/core.

For build:

kwrun build.ts

This will generate an npm folder with generate js main file and .d.ts file declarations

Why?

  • For fun
  • Win32 stuff, easy to do with .NET Framework (installed on all machines), hard with Node.js (maybe Registry for example)
  • Explore .NET 6 (.NET Core)
  • Any other solution

Features

  • Access any .NET component: Type / Class / Object
  • Load dinamycally .NET DLLs
  • Call any method, property directly like any function in javascript/typescript
  • Access to static members, including Structs, Enums, Generics, etc.
  • Compile C# code at run time
  • Supports pass javascript objects as dynamic (ExpandoObject) to C#.

Differences with edge.js

  • Edge execute .NET/Mono/.NET Framework in same process, typedotnet create a separated process.
  • Due to in-process execution, Edge can be faster in some cases.
  • typedotnet allows start many instances of Inter-process comunication, for example running .NET 6 and .NET Framework simultaneously.
  • typedotnet can call (almost?) all existing function without compile C# code, Edge needs Methods with specific signature to call. This means, Edge needs pre-compilation or dynamic compilation, giving some overhead to initialization, with typedotnet this can be avoided.
  • typedotnet doesn't require any native dependency, good for restricted environments or small operations.

How works?

typedotnet creates another process with .NET Core or .NET Framework/Mono, and comunicate between stdio pipes, using JSON serialization. This makes slower than Edge.js but, also means that is not required native dependencies, nor development environment to install. Also, at least for .NET Core, you can execute on any architecture where can be installed.

typedotnet can also access to private properties or methods, using the prefix: hidden_

Execute existing methods or accessing to existing types/classes is possible thanks to kodnet project.

typedotnet exposes a Dotnet class from what you can do anything:

import {Dotnet} from '@kwruntime/typedotnet'
async function main(){
    let dot = new Dotnet()

    // start with .NET Core
    await dot.start("netcore")

    // or start with .NET Framework/Mono 
    await dot.start("netframework")
}

The idea with typedotnet is create a "Batch" execution, and finish after the operations you need do.

import {Dotnet} from '@kwruntime/typedotnet'
async function main(){
    let dot = new Dotnet()

    // start with .NET Core
    await dot.start("netcore")
    
    
    for(let i=0;i<1000;i++){
        await executeSomeOperation()
    }

    // finish dotnet instance if all work finished
    dot.close()
}


async function executeSomeOperation(dot){

    let batch = dot.batch()

    // execute all your stuff 
    ...

    // finish and free al memory used
    await batch.finish()

}

Access to existing types/classes:

const dot = new Dotnet()
// start with .NET Core
await dot.start("netcore")
    
const scope = dot.batch()
let sbStatic = scope.static("System.Text.StringBuilder")

// Contructors are construct method 
let sb = sbStatic.construct()
sb.AppendLine("Línea 1")
sb.AppendLine("Línea 2")
sb.Append("Prueba1,")
sb.Append("Prueba2,")
sb.Append("Prueba3")

// typedotnet selects the best overload call to method automatically
sb.AppendLine()

// if you need get the value in javascript use batch.wait 
console.info(await scope.wait(sb.ToString()))

// properties can be accessed like any other method
console.info(await scope.wait(sb.Length()))


// finish scope 
await batch.finish()

Compiling C# code it's possible:

const dot = new Dotnet()
// start with .NET Core
await dot.start("netcore")

let batch = dot.batch()

let startup = await batch.compile({
    source: `
    using System;
    using System.Collections.Generic;
    using System.Threading.Tasks;


    class Startup{
        public object Invoke(dynamic person){
            return new {
                Text = "Welcomes from .NET " + (string )person.name + " Your age is: " + person.age.ToString()
            };
        }
    }

    `,
    // doesn't matter if is private
    typename: "Startup"
})

let person = {
    name:"James",
    age: 28
}     
// javascript objects are sent as dynamic ExpandoObjects
let result = await batch.wait(startup.Invoke(person))

// this will shows something like this: Result: { '$id': '2', Text: 'Welcomes from .NET James Your age is: 28' }
console.info("Result:", result)

await batch.finish()

If you are only executing void actions, you need call batch.execute() instead of batch.wait for get result.

const dot = new Dotnet()
// start with .NET Core
await dot.start("netcore")

let batch = dot.batch()

// your stuff 
... 

try{
    // no need to get any value from execution, so call .execute() instead of .wait 
    await batch.execute()

}catch(e){
    // control exceptions

    // full stack trace 
    console.error(e)

    // only dotnet stacktrace if available
    console.error(e.dotnetStackTrace)
}

await batch.finish()

You can set properties like any other javascript object. Consider this example similar to compile example:

const dot = new Dotnet()
// start with .NET Core
await dot.start("netcore")

let batch = dot.batch()

let startup = await batch.compile({
    source: `
    using System;
    using System.Collections.Generic;
    using System.Threading.Tasks;

    public class Person{
        public string name {get;set;}
        public int age {get;set;}
    }

    class Startup{
        public object Invoke(Person person){
            return new {
                Text = "Welcomes from .NET " + person.name + " Your age is: " + person.age.ToString()
            };
        }
    }

    `,
    // doesn't matter if is private
    typename: "Startup"
})

let person = batch.static("Person").construct()
person.name = "James"
// this is needed because JSON.NET convert javascript numbers to long instead of int
person.age = batch.utils.Cast(28, "System.Int32")

let result = await batch.wait(startup.Invoke(person))

// this will shows something like this: Result: { '$id': '2', Text: 'Welcomes from .NET James Your age is: 28' }
console.info("Result:", result)

await batch.finish()

API Reference