C#とNode.jsを連携する その２

####C#とNode.jsを連携する

#####コンソールアプリを利用する

EdgeJSはC#のソースを文字列にしそれをコンパイルしています。ソースだろうがファイルだろうがDllだろうがC#を一旦文字列化し、再度ビルドします。
Nugetを読んでたり、外部DLLを参照していたり、Puhblishで書き出したものをすべて読み込んだりすると、Dllが足りなかったり、バージョン違いのedgeJSを上書きしてしまったりで、いろいろうまく動作しないことが多いです。
プログラムが複雑になると開発が難しくなる懸念があります。
そこでC#のコンソールアプリを別個に作り、外部プロセスでコンソールアプリを実行し引数でjsonを投げ、結果をJsonで標準出力しNodeJs側で取得するというのが開発効率がよいと考えました。

####サンプルファイル

一式をGitに上げました

https://github.com/iotagtk1/nodeJsEdgeJSApp

####Node.jsから実行されるC＃

```js
process.env.EDGE_USE_CORECLR = 1;
process.env.EDGE_DEBUG=1;
process.env.EDGE_NATIVE='edge-js/build/Release/edge_coreclr.node';

const edge = require('edge-js');

var add = edge.func({
    source: path.join(__dirname, '../ConsoleApp1/clsTest.cs') ,
    references: ['System.IO', 'System.Diagnostics.Process']
});

add('Node.js', function (error, result) {
    if (error) throw error;
    console.log("result   " + result);
});
```

####Node.jsから実行されたC＃からC#コンソールアプリを呼ぶ

コンソールアプリを呼びだするだけのシンプルなものです。引数でJsonを渡す

```cs
public class Startup
{
    public async Task<object> Invoke(object input)
    {
        
        System.Diagnostics.Process p = new System.Diagnostics.Process();
        // 子プロセスの実行ファイル名
        p.StartInfo.FileName = "ConsoleApp1/bin/Debug/net5.0/ConsoleApp1";
        // 子プロセスのオプション（もしあれば）
        p.StartInfo.Arguments = "-n";
        // コンソール・ウィンドウを開かない
        p.StartInfo.CreateNoWindow = true;
        // シェル機能を使用しない
        p.StartInfo.UseShellExecute = false;
        // 標準出力をリダイレクト
        p.StartInfo.RedirectStandardOutput = true;
        // 標準入力をリダイレクト
        p.StartInfo.RedirectStandardInput = true;
        p.Start(); // 子プロセスの実行開始
        // 子プロセスの出力の読み込み
        string output2 = await p.StandardOutput.ReadToEndAsync();            
        p.WaitForExit();
        // p.WaitForExitAsync(); // 子プロセスが終了するのを待つ こっちだとエラーが出た
        p.Dispose(); // 子プロセスの破棄       
        return output2;
    }		
}
```

####C#コンソールアプリ内でいろいろやれる

Nugetを読んだり、外部ライブラリを使ったり、いつもどおりのＣ#プログラミングをやる

```cs
    class Program
    {        
        private static Timer MyTimer;
        static void Main(string[] args)
        {
            RestClient client = new RestClient();
            RestRequest request = new RestRequest();            

            // RestAPIから情報取得のためにアクセスする、e-StatのURLです(json用) 
            client.BaseUrl = new Uri("http://api.e-stat.go.jp/rest/3.0/app/json/getStatsData");

            // HTTPのコマンドを指定します、情報の取得なので GET を指定します
            request.Method = Method.GET;

            // リクエストを送信します
            var response = client.Execute(request);

            //Thread.Sleep(1000);  
            Console.WriteLine("--------111-----------------" + response.Content );
            // Thread.Sleep(1000);
            Console.WriteLine("--------222-----------------" + request.ToString());
            // Thread.Sleep(2000);            
            Console.WriteLine("--------333-----------------");
        }
    }
```

####実行結果

コンソールアプリで実行したものをすべて取得してからnode.jsに返ってきました。標準出力でJsonを表示し取得する
<img width="500" alt="Screenshot from 2021-10-20 17-16-55.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/182324/c2e23767-8fb7-12ad-9f8e-5e0da52a473e.png">

####C#のEdgeJS中身を考察

EdgeJSのC＃EdgeCompiler.csを見ることでReadMeに書かれていないやり方で実装方法が発見できます。

EdgeCompiler.csを読むとNodeJsからパラメーターで送るとC#側でSystem.Runtimeなど処理を自動で読み込んでいる処理がわかる。
System.Runtimeなどはコンパイル文のC#側でUsingを書く必要がないです。それ以外のアセンブリはreferencesで設定して読み込みます。

<img width="500" alt="Screenshot from 2021-10-20 14-28-14.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/182324/b9256731-220b-0994-d3f7-e11cd619352d.png">

https://qiita.com/iota_11/items/33b25369f13435aff999

####EdgeJS C#側で読み込めるDllファイルの制限

読み込めるDllファイルは制限があります。バージョンの新しいもの(NetStandard2.0以降?)は読み込めないことが多いようです。
読み込めるDllファイルを確認するにはEdgeCompiler.csのcompileAssembliesの値をデバッグするとわかります。
<img width="500" alt="Screenshot from 2021-10-20 16-57-02.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/182324/32ef2a9f-857c-4d92-5c61-b8946c9bdac3.png">

####感想

C#の再ビルドはいろいろ不具合が予想されるのでシンプルにし、外部コンソールアプリから実行してやるのが一番だと思いました。


####追記

node.jsにはが外部プロセスを実行するプログラムがあったのでこれを使ったほうがよい気がしてきました。

https://maku77.github.io/nodejs/io/child-process.html


[C#とNode.jsを連携する 最終章](https://qiita.com/iota_11/items/254e920cedc88182b110)に続く