[C#] Edge.js を触ってみた


 .NET で Node.js できたり、 Node.js で .NET できたりする Edge.js を C# で触ってみたのでメモしておきます。

今回は C# 側から Node.js を使うところをやりたいと思います。
~~javascript から .NET の部分についてはまた別の機会にできたらと思います。~~
[javascript から .NET の部分についても記事を作成しました。](http://qiita.com/t-koyama/items/1acdc8d52e7ed0ebd940#_reference-90d78d72e5ac4470cc10)

Edge.js についての詳細は以下を参照してください。

* [Edge.js](http://tjanczuk.github.io/edge/#/)
* [GitHub - tjanczuk/edge: Run .NET and Node.js code in-process on Windows, MacOS, and Linux](https://github.com/tjanczuk/edge/tree/master)

# 開発環境

Windows 10 Pro
Visual Studio 2015 Community
.NET Framework 4.5.1

# パッケージの入手
パッケージマネージャーコンソールから以下のコマンドを入力します。

Install-Package Edge.js

追記
.NET から Node.js を使う場合は、Node.js のインストールは必須ではないようです。(npm でパッケージを追加したい場合は Node.js が必要となります。)
[https://github.com/tjanczuk/edge#what-you-need-1](https://github.com/tjanczuk/edge#what-you-need-1)

# Hello World
公式の Hello World 的なやつです。

```csharp
using System;
using System.Threading.Tasks;
using EdgeJs;

namespace SampleEdgeApp
{
    class Program
    {
        static void Main(string[] args)
        {
            Func<Task> sample1 = async () =>
            {
                var func = Edge.Func(@"
                    return (data, callback) =>
                        callback(null, 'Node.js welcomes ' + data);
                ");

                Console.WriteLine(await func(".NET"));
            };

            sample1().Wait();
        }
    }
}
```

`Edge.Func()` の引数に javascript のコードを文字列で与えてあげると `Func<object, Task<object>>` を返してくれます。

# 連想配列を受取る
連想配列を受取ってみます。

```csharp
using System;
using System.Threading.Tasks;
using System.Linq;
using EdgeJs;

namespace SampleEdgeApp
{
    class Program
    {
        static void Main(string[] args)
        {
            Func<Task> sample2 = async () =>
            {
                var func = Edge.Func(@"
                    return (data, callback) => {

                        var filter = data.filter(x => x % 2 == 0);
                        var map = data.map(x => x * 2);
                        var sum = data.reduce((x, y) => x + y, 0);

                        console.log('-- javascript -----------------------------------------------')
                        console.log(filter.reduce((x, y) => x + ',' + y));
                        console.log(map.reduce((x, y) => x + ',' + y));
                        console.log(sum);

                        callback(null, {
                            filter : filter,
                            map : map,
                            sum : sum
                        });
                    };
                ");

                dynamic items = await func(Enumerable.Range(1, 10));
                Console.WriteLine("-- csharp ---------------------------------------------------");
                Console.WriteLine(string.Join(",", items.filter));
                Console.WriteLine(string.Join(",", items.map));
                Console.WriteLine(items.sum);
            };

            sample2().Wait();
        }
    }
}
```
C# 側から `IEnumerable<int>` を引数で渡して、javascript 側でごにょごにょしてから連想配列にして返してます。
C# 側で受け取るときは `dynamic` 型を使います。

# 匿名型

匿名型を引数に javascript 側に渡してみます。

```csharp
using System;
using System.Threading.Tasks;
using EdgeJs;

namespace SampleEdgeApp
{
    class Program
    {
        static void Main(string[] args)
        {
            Func<Task> sample3 = async () =>
            {
                var func = Edge.Func(@"
                    return (data, callback) => {
                        callback(null, 'name : ' + data.name + ', age : ' + data.age);
                    };
                ");

                Console.WriteLine(await func(new { name = "太郎", age = 21 }));
            };

            sample3().Wait();
        }
    }
}
```

同様に `class` や `struct` も渡せます。

# js ファイルの読込み
モジュールを作成して C# から使ってみます。

## javascript

```javascript:sample.js
module.exports = (data, callback) => callback(null, data + 1);
```

作成したJSファイルは出力ディレクトリにコピーするようにしておきます。

## C#  

```csharp
using System;
using System.IO;
using System.Threading.Tasks;
using EdgeJs;

namespace SampleEdgeApp
{
    class Program
    {
        static void Main(string[] args)
        {
            Func<Task> sample4 = async () =>
            {
                var add = Edge.Func(@"return require('./../sample.js')");

                Console.WriteLine(await add(1));
            };

            sample4().Wait();
        }
    }
}
```

作成したモジュールを `require()` した結果を C# 側で使っています。

# HTTPサーバー
`http.createServer()` を使って、簡単な HTTPサーバーを作成してみます。

```csharp
using System;
using EdgeJs;

namespace SampleEdgeApp
{
    class Program
    {
        static void Main(string[] args)
        {
            Action start = async () =>
            {
                var createHttpServer = Edge.Func(@"
                    var http = require('http');

                    return (port, cb) => {
                        http.createServer((req, res) => {
                        res.writeHead(200, {
                            'Content-Type': 'text/plain; charset=utf-8'
                        });
                        res.end('Hello, world! ' + new Date());
                    }).listen(port, cb);
                    };
                ");

                await createHttpServer(8080);
            };

            start();

            Console.ReadLine();
        }
    }
}
```

# 参考
_Edge.js_
[http://tjanczuk.github.io/edge/#/](http://tjanczuk.github.io/edge/#/)

_GitHub - tjanczuk/edge: Run .NET and Node.js code in-process on Windows, MacOS, and Linux_
[https://github.com/tjanczuk/edge/tree/master](https://github.com/tjanczuk/edge/tree/master)

_働くプログラマ - MEAN あれこれ: Edge.js の使用_
[https://msdn.microsoft.com/ja-jp/magazine/mt703440.aspx](https://msdn.microsoft.com/ja-jp/magazine/mt703440.aspx)