记录创建纯nodejs模块踩坑流程

[仅作学习,切莫多鸠余.由头到尾模仿一遍]

目的:创建一个模块基于C#调用的封装.能够被nodejs调用

----------------坑坑坑坑坑坑坑-------------
首先,根据度娘的发现能够实现此功能的第三方依赖模块为edge.但实际测试会报错.于是发现有个electron-edge-js,但发现这个需要安装electron.所以觉得太不存粹了.最后发现可怜的有个edge-js.网友说是edge的修复版,最终通过测试.可是还有一个坑,就是发现require的每个函数都会生成一个DLL的内存.问了同事说electron-edge-js不会.
哎,没办法.只能想办法了.
因为考虑到以上三个包都需要c#那边的函数以Func>的形式进行声明,如果这种格式不熟的话.意思就是要以下这样的格式当然了.还有Framework 4.6以上咯.或者.net standard好像也可以
public async Task JSProxyInvoke(dynamic args){

}
如果按照这样的逻辑.也就是每次第三方的DLL都需要封装一层c#DLL.(PS.多么的麻烦,或者我理解错了?但是看GitHub好像是这个意思呀)
最后,想到通过中间一个负责反射的DLL,就可以实现一个C#DLL中转所有的第三方DLL.这样的话.就不用nodejs也封装一次,C#这边也要封装一次了
----------------坑坑坑坑坑坑坑-------------

创建C#中间通用模块

根据以上的想法,需要创建一个通用的中间DLL作为使用.同时中间DLL的指定会 被封装在模块中,这样其他人调用只需要知道目标DLL是什么和函数接口参数等信息就可以了.省去中间的require等操作.

//C# 创建一个DLL项目 DynamicJSProxy.dll 其中的核心代码
        public async Task JSProxyInvoke(dynamic args) {
             JSProxyResult proxyResult = new JSProxyResult();
             BindingAssemblyResolveEvent();//用于反射时缺依赖DLL时加载
             string AssemblyFile = "";
             string TypeName = "";
                 AssemblyFile=(string)args.AssemblyFile;//Dll的名字
                 TypeName = (string)args.TypeName;//类名
          
             if (!AssemblyCreateInstance(AssemblyFile, TypeName)) return proxyResult;
             MethodInfo method = AssemblyObject.GetType().GetMethod((string)args.MethodName, BindingFlags.Instance | BindingFlags.Public);
             ParameterInfo[] pis = method.GetParameters();
             object[] invoteParams = new object[pis.Length];
            if (pis.Length == 0)
            {
                proxyResult.RESULT = 0;
                proxyResult.MSG = "成功";
                dynamic dynamicOut= method.Invoke(AssemblyObject, invoteParams);//没参数的情况传递
                proxyResult.DATA = new
                {
                    IN = invoteParams,
                    OUT = dynamicOut
                };
                 return proxyResult;
             }
 
             if (args.Parameters is ExpandoObject)
             {
                 IDictionary ParameterDictionary = (IDictionary)(args.Parameters);

                 for (int i = 0; i < pis.Length; i++) //复制数据进去
                 {
                     invoteParams[i] = ParameterDictionary.Values.ElementAt(i);
                 }
                proxyResult.RESULT = 0;
                proxyResult.MSG = "成功";
               
                dynamic dynamicOut = method.Invoke(AssemblyObject, invoteParams);//没参数的情况传递
                proxyResult.DATA = new
                {
                    IN = invoteParams,
                    OUT = dynamicOut
                };
                return proxyResult;
             }
             return proxyResult;
        }

        public JSProxy() {
            string EnvironmentPATH = Environment.GetEnvironmentVariable("PATH");
            AssemblySearchBaseDir = System.IO.Path.GetDirectoryName(this.GetType().Assembly.Location);//获取DLL所在地址
            string p = AssemblySearchBaseDir;
            string newPath = string.Join(System.IO.Path.PathSeparator.ToString(), EnvironmentPATH, p);
            Environment.SetEnvironmentVariable("PATH", newPath);
        }
        class JSProxyResult
        {
            public int RESULT { get; set; } = -1;
            public string MSG { get; set; } = "失败";
            public dynamic DATA { get; set; }
        }

 
 

这个DynamicJSProxy.dll作为中转使用

初始化项目

接下来需要创建一个跟这个中转DLL配合使用的模块
创建空白文件夹DynamicJSProxy
根据流程创建了一个模块项目DynamicJSProxy模块,用于调用C# DLL DynamicJSProxy.dll来实现功能.
在DynamicJSProxy中使用命令行进行模块的初始化

//初始化生成package.json
cnpm init
//也可以使用cnpm init --yes 直接默认过去.
//输入相应的package.json的信息

安装依赖

然后使用cnpm install 安装edge-js模块.
----------------坑坑坑坑坑坑坑-------------
注意:这个坑坑了我不少.如果是使用模块可以直接cnpm install edge-js就可以了
但是如果后面还要作为第三方依赖的库的话.这样安装依赖的包就不会记录到package.json中的dependencies中,之后引用这个包就会报没有相应的依赖项.很是麻烦
解决办法就是记住要后面加--save
----------------坑坑坑坑坑坑坑-------------

安装edge-js包

cnpm install edge-js --save

安装完成后package.json就会如下这样有依赖信息


image.png

创建入口

接下来创建入口
打开vscode使用打开目录的功能


image.png

添加index.js文件

var edge = require("edge-js");
//var url = require('url');
//var util = require('util');
//定义通用的调用函数中转站代理通用不用更改
//此处有个坑,assemblyFile如果直接使用.Lib/DynamicJSProxy.DLL会导致作为安装包时,报错,因为找的目录时当前目录而不是我们自己创建的dynamic_jsproxy目录,所以使用__dirname就时用来获取js代码所在的路径.这样就准确了
var JSProxyInvoke=edge.func({
    assemblyFile:__dirname+"/Lib/DynamicJSProxy.Dll",
    typeName:"DynamicJSProxy.JSProxy",
    methodName: "JSProxyInvoke"
})
//引出函数JSPorxy作为调用
module.exports.JSProxy= function(MethodInfo,callback){
  if (process.platform != 'win32'){
    this.$notify.error({
      title: '错误',
      message: '此功能为windows专属功能,mac无法使用'
    });
    return;
  }

  JSProxyInvoke(MethodInfo, callback);//加载成功
};

测试

添加测试文件 app.js文件

var DynamicJSProxy=require('./index');
var MethodInfo = {
    AssemblyFile:'CardLibDp.dll',
    TypeName:'CardLibDp',
    MethodName: 'JKE700A_SerialNumber',
    Parameters:{
        prtName:'700A'

    }
}
DynamicJSProxy.JSProxy(MethodInfo, function (err, val) {
    if (err) throw err
    console.log(val)
    
  });

可以直接vscode使用F5进行直接调试.不过,如果调试app.js就会报错.暂时没由仔细去解决.
我直接使用命令运行,去到app.js目录

>node app.js
{ RESULT: -1, MSG: '失败', DATA: null }

到此模块创建和测试完毕

上传模块

使用命令进行私有npm仓库上传

//使用login登录
>npm login --registry=http://X.X.X.208:1000
Username: XXX
Password:
Email: (this IS public) [email protected]
Logged in as hrf on http://X.X.X.208:1000/.
//看到这句,说明成功了

上传

>npm publish --registry=http://X.X.X.208:1000
npm notice
npm notice package: [email protected]
npm notice === Tarball Contents ===
npm notice 303B   package.json
npm notice 342B   app.js
npm notice 610B   index.js
npm notice 13.8kB Lib/DynamicJSProxy.dll
npm notice === Tarball Details ===
npm notice name:          dynamic_jsproxy
npm notice version:       0.0.3
npm notice package size:  7.4 kB
npm notice unpacked size: 15.1 kB
npm notice shasum:        4c2f1566aadf6c6db3043a0a9aa553e935d895a6
npm notice integrity:     sha512-b/zr265Ue3q7V[...]5KhQ1Q6Uv0JwA==
npm notice total files:   4
npm notice
+ [email protected]

以上为上传到私有仓库中的模块.使用时只需要在使用的模块中使用

>npm install dynamic_jsproxy --registry=http://X.X.X.208:1000

在node_model中就会看到dynamic_jsproxy.这样就可以直接使用
使用方式

var DynamicJSProxy=require('dynamic_jsproxy');
var MethodInfo = {
    AssemblyFile:'CardLibDp.dll',
    TypeName:'CardLibDp',
    MethodName: 'JKE700A_SerialNumber',
    Parameters:{
        prtName:'AISINO JKE700A'

    }
}
DynamicJSProxy.JSProxy(MethodInfo, function (err, val) {
    if (err) throw err
    console.log(val)
    
  });

你可能感兴趣的:(记录创建纯nodejs模块踩坑流程)