通过jint+ es6 模块设计一个插件化系统代码简单说明

属于原型代码,比较粗糙,属于示例部分代码比较简单

代码结构

代码基于了ioc ,整体比较简单,核心是说明下设计思路以及一些简单代码实现

  • 代码结构
├── MyDbContext.cs
├── Program.cs
├── QueryService.cs
├── jint-apps.csproj
└── modules
    └── loginplugin
        └── userlogin.js
  • 参考玩法

比如了EF,暴露dbcontext 一些能力为dao,方便业务使用,然后暴露一些能力服务到@scope/platform-common es 6 模块中,对于开发的js plugin 直接导入common module,实现业务开发,更加合理的做法是对于js plugin 应该定义一套标准接口,这样调用也就比较统一了

代码说明

代码比较简单,MyDbContext.cs 属于一个基于EF 定义的数据访问层,QueryService.cs 是业务包装,里边有暴露common 能力到jint 中以及一个简单的调用js plugin 的处理,属于简单演示,modules/loginplugin/userlogin.js 是简单插件代码,

  • MyDbContext.c

sqlite dbcontext

using Microsoft.EntityFrameworkCore;

namespace JintApp;
public class MyDbContext: DbContext
{
    public DbSet<User> Users => Set<User>();
    public MyDbContext(DbContextOptions<MyDbContext> options) : base(options) { }
}

public class User
{
    public int Id { get; set; }
    public string Name { get; set; } = "";

    public override string ToString()
    {
        return $"Name is: {Name}, Id is:{Id}";
    }
}
  • QueryService.cs
using System.Diagnostics.CodeAnalysis;
using Jint;
using Jint.Native;
using Jint.Runtime.Modules;

namespace JintApp;

[RequiresUnreferencedCode("Calls Jint.Engine.SetValue<T>(String, T)")]
public class QueryService
{
    private readonly MyDbContext _dbContext;
    private readonly Engine _engine;
    // 此处通过ioc 注入依赖
    public QueryService(MyDbContext myDbContext, Engine engine)
    {
        _dbContext = myDbContext;
        _engine = engine;
        InitEngineQueryMethod();
    }

    private void InitEngineQueryMethod()
    {
       // 暴露一些常用方法,比如console 日志的
        _engine.SetValue("console", new
        {
            log = (Action<object>)Console.WriteLine,
            error = (Action<object>)(Console.Error.WriteLine),
        });
      // 演示暴露platform 核心能力服务,funcs 是一些公共方法函数,
        var platform = new
        {
            funcs = new
            {
                queryDb = (Func<string, string>)((name) =>
                {
                    var users = _dbContext.Users.Where(u => u.Name == name).Select(u => u.Name + u.Id);
                    string userinfos = string.Join(", ", users);
                    return userinfos;
                }),
                init = (Func<string?, string>)((name) =>
                {
                    Console.WriteLine("jint init");
                    return "ok";
                }),
                add = (Func<double, double, double>)((a, b) => a + b)
            }
        };
        // common es 6 模块暴露
        _engine.Modules.Add("@scope/platform-common", builder => { builder.ExportObject("platform", platform); });
    }

    public void ExecuteQuery(string userName)
    {
        try
        {
            // 调度插件,当然此处基于了文件路径模式,也可以基于text code 模式
            var ns = _engine.Modules.Import("./loginplugin/userlogin.js").Get("queryUser").AsObject();
            var fn = ns.Get("qv2Async").AsFunctionInstance();
            var result = fn.Call(userName).UnwrapIfPromise();
            Console.WriteLine($"Query result: {result}");
        }
        catch (Exception ex)
        {
            Console.WriteLine($"Error executing query: {ex.Message}");
        }
    }
}
  • userlogin.js

简单示意,就是一个标准的es6 模块,引用了通过native 暴露的common 方法

import  {platform} from  "@scope/platform-common"
export const   queryUser = {
    name: "dalong demo",
    qv2: platform.funcs.queryDb,
    add: platform.funcs.add,
    init: platform.funcs.init,
    qv2Async:platform.funcs.queryDb
}
  • Program.cs

入口代码,记性ioc 服务的注册,以及简单业务访问

using Jint;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.DependencyInjection;

namespace JintApp;

public class Program
{
    static void Main()
    {
        var services = new ServiceCollection();
        services.AddDbContext<MyDbContext>(options =>
            options.UseSqlite("Data Source=example.db"));
        services.AddSingleton<Engine>(s =>
        {
            return new Engine(options =>
            {
                // 基于硬编码的路径,可以结合自己的场景修改,推荐基于代码控制
                options.EnableModules("/Users/dalong/RiderProjects/serail-apps/jint-apps/modules");
            });
        });;
        services.AddSingleton<QueryService>();
        var serviceProvider = services.BuildServiceProvider();
        var queryService = serviceProvider.GetRequiredService<QueryService>();
        for (var i = 0; i<1; i++)
        {
            // 调用服务
            queryService.ExecuteQuery("Alice");
        }
    }
}

说明

以上代码比较简单,核心是简单演示下基于js 引擎的插件处理,后续看情况完善下实现,形成一个完整的解决方案

参考资料

https://github.com/sebastienros/jint

https://github.com/microsoft/node-api-dotnet

https://github.com/microsoft/ClearScript

posted on 2025-07-20 08:00  荣锋亮  阅读(16)  评论(0)    收藏  举报

导航