NeuCharFramework (NCF)
  • NCF - NeuCharFramework
  • 项目

    • 准备
    • 基础库源码分析
    • 动态WebApiEngine
    • 部署
    • MCP (Model Context Protocol) 模块
    • Senparc.AI
  • 帮助

    • 在线资源
    • 问答社区
    • QQ群(147054579)
    • Senparc微信SDK
  • Gitee
  • GitHub
  • English
  • 简体中文
GitHub
  • NCF - NeuCharFramework
  • 项目

    • 准备
    • 基础库源码分析
    • 动态WebApiEngine
    • 部署
    • MCP (Model Context Protocol) 模块
    • Senparc.AI
  • 帮助

    • 在线资源
    • 问答社区
    • QQ群(147054579)
    • Senparc微信SDK
  • Gitee
  • GitHub
  • English
  • 简体中文
GitHub
  • NCF 概要

    • NCF - NeuCharFramework
    • 关于 NCF
    • 环境要求
    • 前后端分离模式
    • Xncf模块简介
  • 准备开发

    • 获取 NCF 模板源码
    • 使用 Visual Studio 运行 NCF
    • 使用 CLI 运行 NCF
    • 安装
    • 管理员登录
    • 管理员后台
    • appsettings.json 配置
    • 模块管理
    • 获取文档
  • 配置

    • 入口文件
    • 数据库设置
    • appsettings.json 配置
    • Docker
    • Dapr
    • 配置多租户
    • Redis 缓存
  • 模块化开发

    • NCF 模块化开发思想
    • Xncf 的构成
    • 创建第一个 Xncf 模块
    • Xncf 模块 Sample 详解
    • 实现自己的业务逻辑
    • 更新 Xncf 模块
    • 模块之间如何调用
    • 发布Xncf 模块到nuget.org
    • 更新基础库
    • Xncf 模块开发
    • 嵌入静态资源文件到NCF中
    • 发布本地Nuget包
    • 进阶
  • 数据库

    • 数据库设置
    • 多数据库支持
    • 指定数据库
    • 更新 Senparc.Service 项目的数据库迁移文件(Migrations)
    • 多数据库原理
    • 数据库停机坪(DatabasePlant)
    • 停机坪操作数据库迁移和更新
  • 单元测试

    • NCF 单元测试介绍
    • 开始开发
    • 进阶
    • 附录
  • Q&A

    • NCF名词解释
    • NCF常见问题
  • 新发布

    • 新功能
    • 升级指导
    • 日志

Xncf 模块开发

NCF 底层支持库官方 Nuget 包源码

Xncf 单功能执行模块开发

1.新建一个Dotnet Core的Class Library项目

create_dotnet_core_class_library

2.输入Class Libray的名称,点击创建

Image text

3.建立Register.cs

Image text

4.配置Register中的必要内容

名称说明
Name模块名称
Uid全球唯一码,最好使用工具生成
Version模块版本号(更新版本靠它识别)
MenuName安装到NCF中以后菜单中显示的名称
Icon显示在菜单旁边的字体图标
Description模块的说明文字,安装前可以根据此说明了解模块的具体功能

Image text

5.创建自定义方法类

Image text

6.完成自定义方法

public MyFunction(IServiceProvider serviceProvider) : base(serviceProvider)
{
}

public class Parameters : IFunctionParameter
{
    [Required]
    [MaxLength(50)]
    [Description("名称||双竖线之前为参数名称,双竖线之后为参数注释")]
    public string Name { get; set; }

    [Required]
    [Description("数字||数字1")]
    public int Number1 { get; set; }


    [Required]
    [Description("数字||数字2")]
    public int Number2 { get; set; }

    [Description("运算符||")]//下拉列表
    public SelectionList Operator { get; set; } = new SelectionList(SelectionType.DropDownList, new[] {
            new SelectionItem("+","加法","数字1 + 数字2",false),
            new SelectionItem("-","减法","数字1 - 数字2",true),
            new SelectionItem("×","乘法","数字1 × 数字2",false),
            new SelectionItem("÷","除法","数字1 ÷ 数字2",false)
    });

    [Description("计算平方||")]//多选框
    public SelectionList Power { get; set; } = new SelectionList(SelectionType.CheckBoxList, new[] {
            new SelectionItem("2","平方","计算上述结果之后再计算平方",false),
            new SelectionItem("3","三次方","计算上述结果之后再计算三次方",false)
    });
}


public override string Name => "我的函数";

public override string Description => "我的函数的注释";

public override Type FunctionParameterType => typeof(Parameters);

public override FunctionResult Run(IFunctionParameter param)
{
    return FunctionHelper.RunFunction<Parameters>(param, (typeParam, sb, result) =>
    {
        /* 页面上点击“执行”后,将调用这里的方法
            *
            * 参数说明:
            * param:IFunctionParameter 类型对象
            * typeParam:Senparc.Xncf.Application.MyFunction.Parameters 类型对象
            * sb:日志
            * result:返回结果
            */

        double calcResult = typeParam.Number1;
        var theOperator = typeParam.Operator.SelectedValues.FirstOrDefault();
        switch (theOperator)
        {
            case "+":
                calcResult = calcResult + typeParam.Number2;
                break;
            case "-":
                calcResult = calcResult - typeParam.Number2;
                break;
            case "×":
                calcResult = calcResult * typeParam.Number2;
                break;
            case "÷":
                if (typeParam.Number2 == 0)
                {
                    result.Success = false;
                    result.Message = "被除数不能为0!";
                    return;
                }
                calcResult = calcResult / typeParam.Number2;
                break;
            default:
                result.Success = false;
                result.Message = $"未知的运算符:{theOperator}";
                return;
        }

        sb.AppendLine($"进行运算:{typeParam.Number1} {theOperator} {typeParam.Number2} = {calcResult}");

        Action<int> raisePower = power =>
        {
            if (typeParam.Power.SelectedValues.Contains(power.ToString()))
            {
                var oldValue = calcResult;
                calcResult = Math.Pow(calcResult, power);
                sb.AppendLine($"进行{power}次方运算:{oldValue}{(power == 2 ? "²" : "³")} = {calcResult}");
            }
        };

        raisePower(2);
        raisePower(3);

        result.Message = $"计算结果:{calcResult}。计算过程请看日志";
    });
}

7.在Register中注册自定义的方法类

Image text

8.发布Nuget,详细步骤到发布Nuget

Xncf 自定义带页面功能模块开发

1.新建一个DotnetCore Class Library项目,输入项目名称

Image text

Image text

1.1 目录名称如下

Image text

1.2 设置项目支持RazorPage功能

Image text

2.Senparc.Xncf.ExtensionAreaTemplate新建模型Color类

using Senparc.Ncf.Core.Models;
using Senparc.Xncf.ExtensionAreaTemplate.Models.DatabaseModel.Dto;
using System;
using System.ComponentModel.DataAnnotations.Schema;

namespace Senparc.Xncf.ExtensionAreaTemplate
{
    /// <summary>
    /// Color 实体类
    /// </summary>
    [Table(Register.DATABASE_PREFIX + nameof(Color))]//必须添加前缀,防止全系统中发生冲突
    [Serializable]
    public class Color : EntityBase<int>
    {
        /// <summary>
        /// 颜色码,0-255
        /// </summary>
        public int Red { get; private set; }
        /// <summary>
        /// 颜色码,0-255
        /// </summary>
        public int Green { get; private set; }

        /// <summary>
        /// 颜色码,0-255
        /// </summary>
        public int Blue { get; private set; }

        /// <summary>
        /// 附加列,测试多次数据库 Migrate
        /// </summary>
        public string AdditionNote { get; private set; }

        private Color() { }

        public Color(int red, int green, int blue)
        {
            if (red < 0 || green < 0 || blue < 0)
            {
                Random();//随机
            }
            else
            {
                Red = red;
                Green = green;
                Blue = blue;
            }
        }

        public Color(ColorDto colorDto)
        {
            Red = colorDto.Red;
            Green = colorDto.Green;
            Blue = colorDto.Blue;
        }

        public void Random()
        {
            //随机产生颜色代码
            var radom = new Random();
            Func<int> getRadomColorCode = () => radom.Next(0, 255);
            Red = getRadomColorCode();
            Green = getRadomColorCode();
            Blue = getRadomColorCode();
        }

        public void Brighten()
        {
            Red = Math.Min(255, Red + 10);
            Green = Math.Min(255, Green + 10);
            Blue = Math.Min(255, Blue + 10);
        }

        public void Darken()
        {
            Red = Math.Max(0, Red - 10);
            Green = Math.Max(0, Green - 10);
            Blue = Math.Max(0, Blue - 10);
        }
    }
}

3.Senparc.Xncf.ExtensionAreaTemplate.Models.DatabaseModel.Dto新建ColorDto类

Image text

using Senparc.Ncf.Core.Models;

namespace Senparc.Xncf.ExtensionAreaTemplate.Models.DatabaseModel.Dto
{
    public class ColorDto : DtoBase
    {
        /// <summary>
        /// 颜色码,0-255
        /// </summary>
        public int Red { get; private set; }
        /// <summary>
        /// 颜色码,0-255
        /// </summary>
        public int Green { get; private set; }
        /// <summary>
        /// 颜色码,0-255
        /// </summary>
        public int Blue { get; private set; }

        private ColorDto() { }
    }
}

4.AutoMapperConfigs增加以下代码

Image text

using Microsoft.EntityFrameworkCore.Metadata.Builders;
using Senparc.Ncf.Core.Models.DataBaseModel;
using Senparc.Ncf.XncfBase.Attributes;

namespace Senparc.Xncf.ExtensionAreaTemplate.Models
{
    [XncfAutoConfigurationMapping]
    public class ExtensionAreaTemplate_ColorConfigurationMapping : ConfigurationMappingWithIdBase<Color, int>
    {
        public override void Configure(EntityTypeBuilder<Color> builder)
        {
            builder.Property(e => e.Red).IsRequired();
            builder.Property(e => e.Green).IsRequired();
            builder.Property(e => e.Blue).IsRequired();
        }
    }
}

5.Senparc.Xncf.ExtensionAreaTemplate.Areas.ExtensionAreaTemplate.Pages下建立页面,更改Index继承为Senparc.Ncf.AreaBase.Admin.AdminXncfModulePageModelBase

Image text

using Microsoft.AspNetCore.Mvc;
using Senparc.Ncf.Core.Enums;
using Senparc.Ncf.Service;
using Senparc.Xncf.ExtensionAreaTemplate.Models.DatabaseModel.Dto;
using Senparc.Xncf.ExtensionAreaTemplate.Services;
using System;
using System.Threading.Tasks;

namespace Senparc.Xncf.ExtensionAreaTemplate.Areas.ExtensionAreaTemplate.Pages
{
    public class DatabaseSample : Senparc.Ncf.AreaBase.Admin.AdminXncfModulePageModelBase
    {
        public ColorDto ColorDto { get; set; }

        private readonly ColorService _colorService;
        private readonly IServiceProvider _serviceProvider;
        public DatabaseSample(IServiceProvider serviceProvider, ColorService colorService, Lazy<XncfModuleService> xncfModuleService)
            : base(xncfModuleService)
        {
            _colorService = colorService;
            _serviceProvider = serviceProvider;
        }

        public Task OnGetAsync()
        {
            var color = _colorService.GetObject(z => true, z => z.Id, OrderingType.Descending);
            ColorDto = _colorService.Mapper.Map<ColorDto>(color);
            return Task.CompletedTask;
        }

        public IActionResult OnGetDetail()
        {
            var color = _colorService.GetObject(z => true, z => z.Id, OrderingType.Descending);
            var colorDto = _colorService.Mapper.Map<ColorDto>(color);
            //return Task.CompletedTask;
            return Ok(new { colorDto, XncfModuleDto });
        }

        public async Task<IActionResult> OnGetBrightenAsync()
        {
            var colorDto = await _colorService.Brighten().ConfigureAwait(false);
            return Ok(colorDto);
        }

        public async Task<IActionResult> OnGetDarkenAsync()
        {
            var colorDto = await _colorService.Darken().ConfigureAwait(false);
            return Ok(colorDto);
        }
        public async Task<IActionResult> OnGetRandomAsync()
        {
            var colorDto = await _colorService.Random().ConfigureAwait(false);
            return Ok(colorDto);
        }
    }
}

6.增加Service类

Image text

using Senparc.Ncf.Core.Enums;
using Senparc.Ncf.Repository;
using Senparc.Ncf.Service;
using Senparc.Xncf.ExtensionAreaTemplate.Models.DatabaseModel.Dto;
using System;
using System.Threading.Tasks;

namespace Senparc.Xncf.ExtensionAreaTemplate.Services
{
    public class ColorService : ServiceBase<Color>
    {
        public ColorService(IRepositoryBase<Color> repo, IServiceProvider serviceProvider)
            : base(repo, serviceProvider)
        {
        }

        public async Task<ColorDto> CreateNewColor()
        {
            Color color = new Color(-1, -1, -1);
            await base.SaveObjectAsync(color).ConfigureAwait(false);
            ColorDto colorDto = base.Mapper.Map<ColorDto>(color);
            return colorDto;
        }

        public async Task<ColorDto> Brighten()
        {
            //TODO:异步方法需要添加排序功能
            var obj = this.GetObject(z => true, z => z.Id, OrderingType.Descending);
            obj.Brighten();
            await base.SaveObjectAsync(obj).ConfigureAwait(false);
            return base.Mapper.Map<ColorDto>(obj);
        }

        public async Task<ColorDto> Darken()
        {
            //TODO:异步方法需要添加排序功能
            var obj = this.GetObject(z => true, z => z.Id, OrderingType.Descending);
            obj.Darken();
            await base.SaveObjectAsync(obj).ConfigureAwait(false);
            return base.Mapper.Map<ColorDto>(obj);
        }

        public async Task<ColorDto> Random()
        {
            //TODO:异步方法需要添加排序功能
            var obj = this.GetObject(z => true, z => z.Id, OrderingType.Descending);
            obj.Random();
            await base.SaveObjectAsync(obj).ConfigureAwait(false);
            return base.Mapper.Map<ColorDto>(obj);
        }

        //TODO: 更多业务方法可以写到这里
    }
}

7.Senparc.Xncf.ExtensionAreaTemplate.Models.DatabaseModel中ExtensionAreaTemplateSenparcEntities里面增加

Image text

using Microsoft.EntityFrameworkCore;
using Senparc.Ncf.XncfBase;
using Senparc.Ncf.XncfBase.Database;

namespace Senparc.Xncf.ExtensionAreaTemplate.Models.DatabaseModel
{
    public class ExtensionAreaTemplateSenparcEntities : XncfDatabaseDbContext
    {
        public override IXncfDatabase XncfDatabaseRegister => new Register();
        public ExtensionAreaTemplateSenparcEntities(DbContextOptions<ExtensionAreaTemplateSenparcEntities> dbContextOptions) : base(dbContextOptions)
        {
        }

        public DbSet<Color> Colors { get; set; }

        //DOT REMOVE OR MODIFY THIS LINE 请勿移除或修改本行 - Entities Point
        //ex. public DbSet<Color> Colors { get; set; }

        //如无特殊需需要,OnModelCreating 方法可以不用写,已经在 Register 中要求注册
        //protected override void OnModelCreating(ModelBuilder modelBuilder)
        //{
        //}
    }
}

8.在Senparc.Web下执行

Image text

using Senparc.Xncf.ExtensionAreaTemplate.Models.DatabaseModel;
using Senparc.Ncf.XncfBase.Database;
using System;
using System.IO;

namespace Senparc.Xncf.ExtensionAreaTemplate
{
    /// <summary>
    /// 设计时 DbContext 创建(仅在开发时创建 Code-First 的数据库 Migration 使用,在生产环境不会执行)
    /// </summary>
    public class SenparcDbContextFactory : SenparcDesignTimeDbContextFactoryBase<ExtensionAreaTemplateSenparcEntities, Register>
    {
        /// <summary>
        /// 用于寻找 App_Data 文件夹,从而找到数据库连接字符串配置信息
        /// </summary>
        public override string RootDictionaryPath => Path.Combine(AppContext.BaseDirectory, "..\\..\\..\\"/*项目根目录*/, "..\\Senparc.Web"/*找到 Web目录,以获取统一的数据库连接字符串配置*/);
    }
}

9.根据实际的Entities的名称,添加数据库更新命令

Image text

add-migration Xncf_AreaTemplate_Init2 -Context ExtensionAreaTemplateSenparcEntities

10.更新新加的数据库表及字段,只需要运行NCF主程序,更新此引用的模块,或者重新安装此模块即可

欢迎贡献代码!

NeuCharFramework

在 GitHub 上编辑此页
上次更新:
贡献者: Jeffrey Su, MLTechnology
Prev
更新基础库
Next
嵌入静态资源文件到NCF中