Kimmking@163.com 2015-01-14
Edge是一种在进程内实现NodeJS与.NET互操作的桥接技术,可以在NodeJS里使用.NET代码和库,也可以在.NET程序里使用NodeJS的代码。
Edge运行需要.netframework4.5,它使用.NET的Task、async、await机制跟NodeJS的event模型匹配。本质上是连接V8引擎和.NET /monoCLR运行时,同时支持Windows、MacOS、Linux。同时它还支持运行于.NET CLR上的各种脚本语言。借由这种进程内的桥接技术,两边的各种类库和其他技术就可以互通有无了,例如NodeJS使用.NET的图像处理库GDI+、直接用ADO.NET操作SQLServer数据库,甚至直接调用Winform的代码实现桌面UI程序等等。
Edge由微软的技术人员 Tomasz Janczuk 创建于2013年2月。
安装Edge很简单,只需要npm install –gd edge即可。
一个最简单的例子hello.js(NodeJS里使用C#代码):
var edge = require ( 'edge' );
var helloWorld = edge.func( function () { /*
async (input) => { // 这里是 C# 代码
return ".NET Welcomes" + input.ToString();
}
*/ });
helloWorld( 'JavaScript' , function (error, result) {
if (error) throw error;
console .log (result);
});
执行node hello.js时,会先调用.net framework编译/* */内的C#代码。然后执行整个混编的程序,整个过程只有一个node.exe的进程。
或另一种用法(C#里使用NodeJS代码):
using System;
using System.Threading.Tasks;
using EdgeJs;
classProgram
{
publicstaticasyncvoidStart()
{
var func = Edge.Func(@"
return function (data, callback) {
callback(null, 'Node.js welcomes ' + data);
}
");
Console.WriteLine(await func(".NET"));
}
staticvoidMain(string[] args)
{
Task.Run((Action)Start).Wait();
}
}
更多信息参见: Edge.js overview
项目Github主页: https://github.com/tjanczuk/edge
除了上面例子提到的NodeJS与C#简单调用对方的代码实现,Edge还可以实现更复杂的功能,
例如从NodeJS传递数据到.NET中去:
var dotNetFunction = edge.func('Edge.Sample.dll');
var payload = {
anInteger:1,
aNumber:3.1415,
aString:'foo',
aBoolean:true,
aBuffer:newBuffer(10),
anArray: [ 1, 'foo' ],
anObject: { a:'foo', b:12 }
};
dotNetFunction(payload, function (error, result) { });
直接把数据和函数传入C#,让C#回调NodeJS的函数:
var edge =require('edge');
var addAndMultiplyBy2 = edge.func(function () {/*
async (dynamic input) => {
var add = (Func<object, Task<object>>)input.add;
var twoNumbers = new { a = (int)input.a, b = (int)input.b };
var addResult = (int)await add(twoNumbers);
return addResult * 2;
}
*/});
var payload = {
a:2,
b:3,
add: function (data, callback) {
callback(null, data.a + data.b);
}
};
addAndMultiplyBy2(payload, function (error, result) {
if (error) throw error;
console.log(result);
});
需要注意的一点,为了防止进程内阻塞NodeJS的事件机制,NodeJS里无法直接调用.NET的方法,必须用Func<object,Task<object>>封装成异步回调方式。
classProgram
{
publicstaticasyncvoidStart()
{
var createWebSocketServer = Edge.Func(@"
var WebSocketServer = require('ws').Server;
return function (port, cb) {
var wss = new WebSocketServer({ port: port });
wss.on('connection', function (ws) {
ws.on('message', function (message) {
ws.send(message.toUpperCase());
});
ws.send('Hello!');
});
cb();
};
");
await createWebSocketServer(8080);
}
staticvoidMain(string[] args)
{
Task.Run((Action)Start);
new ManualResetEvent(false).WaitOne();
}
}
简简单单,So easy!
只需要用 NuGet 安装Edge.JS,然后把node_modules复制到ASP.NET的webapplication里的bin目录即可。
以python为例,3个步骤:
1) 安装依赖
npm install edge
npm install edge-py
2) 写混编代码
var edge =require('edge');
var hello = edge.func('py', function () {/*
def hello(input):
return "Python welcomes " + input
lambda x: hello(x)
*/});
hello('Node.js', function (error, result) {
if (error) throw error;
console.log(result);
});
3) 执行
$>node py.js
Python welcomes Node.js
NodeJS程序hello.js如下:
<span style="font-size:18px;">var edge = require('edge'); var hello = edge.func(function () {/* #r"System.Data.dll" #r"System.Windows.Forms.dll" #r"System.Drawing.dll" using System.Data; using System.Threading.Tasks; usingSystem.Windows.Forms; usingSystem.ComponentModel; usingSystem.Drawing; async(input) => { Formf = new Form(); f.Text = "大漠穷秋"; Label l = new Label(); l.SetBounds(10, 10, 150, 20); l.Text = "飞猪"; f.Controls.Add(l); TextBox t = new TextBox(); t.SetBounds(10, 35, 150, 20); t.Text = "理工男";f.Controls.Add(t); ComboBox c = new ComboBox(); c.SetBounds(10, 60, 150, 20); c.Text ="翟伟"; f.Controls.Add(c); Button b = new Button(); b.SetBounds(10, 85, 150, 30); b.Text = "棒棒糖";f.Controls.Add(b); b.Click += (oo, ee) => { MessageBox.Show("this applicationcreated by KimmKing", "边边says"); }; l.BackColor = Color.Green; l.ForeColor = Color.Tomato; f.ShowDialog(); return".NET welcomes " + input.ToString(); } */}); hello('Node.js', function (error, result) { if(error) throw error; console.log(result); });</span>
执行node hello.js,效果如下(官方没有这个方面的demo):
3、总结&&个人看法
Edge作为一个桥梁,打通了两个平台的任督二脉,基本上两边原有的东西,都可以相互调用,极大的增强了两个体系的功能拓展。
缺点也很明显:
1、性能:拿NodeJS调用C#来说,比原生的NodeJS差不少,see: Edge性能
2、融合:因为是桥接技术,其实还是两个完整独立的体系,无法细粒度的融合,比如直接用js调用winform的组件实现一套NodeJS的UI技术(如果要实现这一点,还需要一个复杂的中间层)。