CodeForge.Editor
1.0.0
dotnet add package CodeForge.Editor --version 1.0.0
NuGet\Install-Package CodeForge.Editor -Version 1.0.0
<PackageReference Include="CodeForge.Editor" Version="1.0.0" />
<PackageVersion Include="CodeForge.Editor" Version="1.0.0" />
<PackageReference Include="CodeForge.Editor" />
paket add CodeForge.Editor --version 1.0.0
#r "nuget: CodeForge.Editor, 1.0.0"
#:package CodeForge.Editor@1.0.0
#addin nuget:?package=CodeForge.Editor&version=1.0.0
#tool nuget:?package=CodeForge.Editor&version=1.0.0
CodeForge 控件使用指南
CodeForge 是一个面向 WPF 的 C# 代码编辑器控件(net48),内置 Roslyn 智能补全、编译诊断波浪线、鸟瞰图、代码配色主题与脚本一键运行能力。目标是:一行 XAML 即可获得完整编辑体验。
CodeForge.sln
├── CodeForge/ 类库(核心)
│ ├── Controls/ CodeEditorControl 及配套渲染器
│ ├── Core/ CodeCompletionService / ReferenceManager
│ └── Models/ 公共数据模型
├── Demo/ 演示程序(XAML 声明式用法 + 编译/运行展示)
└── DemoUserLibrary/ 演示用外部 DLL 项目
1. 快速开始
安装方式
NuGet 包(推荐,依赖已全部嵌入 DLL 内):
Install-Package CodeForge.Editor
或源码集成:将 CodeForge/ 目录加入你的解决方案,或直接引用 CodeForge.csproj。
单文件分发的说明:依赖 DLL 已在构建时嵌入 CodeForge.dll 本体,宿主只需分发这一个文件;
但 XAML 里若使用了随包的 HandyControl 类型(如 hc:Window),请在 App 静态构造里调用一次:
static App()
{
CodeForge.CodeForgeRuntime.Initialize(); // 入口最早处,先于 InitializeComponent
}
最小可用示例(XAML)
<Window ...
xmlns:cf="clr-namespace:CodeForge;assembly=CodeForge">
<cf:CodeEditorControl x:Name="Editor"
ShowMiniMap="True"/>
</Window>
仅此而已。控件构造时会自动完成:
- 创建 AvalonEdit 编辑器(C# 语法高亮、行号、折叠、当前行高亮)
- 搭建 Roslyn Workspace + MEF 补全管线(默认预置 10 个基础 BCL 引用)
- 初始化内置鸟瞰图、补全弹窗、签名帮助弹窗
后台代码给个初始内容即可开始工作:
Editor.Code = "public class Demo { }";
2. XAML 配置属性一览
| 属性 | 类型 | 默认值 | 说明 |
|---|---|---|---|
Code |
string | 内置欢迎示例 | 编辑器内容(双向:用户编辑会触发 CodeChanged) |
ShowMiniMap |
bool | True |
是否显示右侧鸟瞰图 |
EditorSkin |
EditorSkinMode | Light |
编辑器亮/暗基调(Light/Dark) |
CodeTheme |
CodeThemePreset | FollowWindow |
整套代码配色主题(见第 4 节) |
EditorFontSize |
double | 14 |
初始字号(Ctrl+滚轮可在 Min~Max 间缩放) |
MinFontSize / MaxFontSize |
double | 8 / 48 |
字号缩放边界 |
EditorFontFamily |
string | "Consolas, Courier New, monospace" |
字体回退列表 |
字体属性是 WPF FontFamily 回退链语法:逗号分隔,从左到右取第一个系统里存在的字体;最后一个可用泛型族名兜底:
EditorFontFamily="Cascadia Code, Consolas, monospace"
EditorFontFamily="Consolas, Sarasa Mono SC, monospace"
3. 内置交互功能速览
| 功能 | 操作 |
|---|---|
| 补全 | 输入标识符/. 自动弹出;Ctrl+Space 强制全量 |
| 提交候选 | Enter / Tab / 双击 |
| 签名帮助 | 在方法括号内自动弹出(重载切换 ↑↓) |
| Snippet | 输入 for/foreach/if/cw 等后 Tab 展开;补全列表选中后 Enter 插入 |
| 文档注释 | 在成员上方空行输入 /// 后按 Enter,自动生成 summary/param/returns 骨架 |
| 缩进 | { 后回车自动缩进一级;输入 } 自动对齐开括号行(VS 同款) |
| 编译波浪线 | 见第 5 节 |
| 折叠 | 大括号块、#region 可折叠 |
| 字体缩放 | Ctrl+滚轮 |
| 右键菜单 | 剪贴板操作 / 显示智能提示 / 注释代码等 |
4. 主题配置
两层独立主题体系:
4.1 编辑器亮暗基调 EditorSkin
只影响编辑器本体(背景/文字/光标/行号/选区):
<cf:CodeEditorControl EditorSkin="Dark"/>
4.2 代码配色主题 CodeTheme
一整套"画面基色 + 语法高亮颜色",内置 8 个预设:
| 枚举值 | 风格 |
|---|---|
FollowWindow(默认) |
跟随窗口亮/暗基调的经典配色 |
VsCodeDark |
VS Code Dark+ |
Monokai |
Monokai |
OneDark |
One Dark Pro |
SolarizedLight / SolarizedDark |
Solarized 成对 |
Nord |
Nord |
TokyoNight |
Tokyo Night |
<cf:CodeEditorControl CodeTheme="OneDark"/>
需要完全自定义时,绕过预设直接给调色板:
Editor.ApplyCodeTheme(new CodeHighlightPalette
{
Name = "我的主题",
EditorBackground = Color.FromRgb(0x10,0x12,0x18),
DefaultForeground = Colors.Gainsboro,
Keyword = Color.FromRgb(0xC7,0x92,0xEA),
Comment = Color.FromRgb(0x5C,0x63,0x70),
StringOrChar = Color.FromRgb(0xE8,0xB0,0x4B),
Number = Color.FromRgb(0xF7,0x8C,0x6C),
Type = Color.FromRgb(0x82,0xAA,0xFF),
Method = Color.FromRgb(0xFF,0xCB,0x6B)
});
// 只覆盖语法色不动背景:Editor.SetCodeHighlightPalette(palette);
注意:窗口整体 UI 的亮暗(按钮/标题栏等 HandyControl 部分)由宿主应用负责,CodeForge 只管编辑器区域。
5. 编译与运行
// 编译当前编辑器内容 → DLL(内存字节)
CodeCompileResult result = Editor.Compile();
// 编译结果可视化:错误=红色波浪线 / 警告=橙黄;编译成功即清空
Editor.ShowCompileDiagnostics(result);
// 手动清空:Editor.ClearCompileDiagnostics();
// 编译并运行 Main(支持实例方法:传入 instance 直接调用现有对象的方法)
var (compile, run) = Editor.CompileAndRun(typeName: "ScriptHost", methodName: "Main");
Console.WriteLine(run?.ConsoleOutput); // 运行期 Console.Out/Error 的捕获输出
Console.WriteLine(run?.Success);
Console.WriteLine(run?.ErrorMessage);
// 其它入口
Editor.CompileToFile(path); // 编译并落盘
Editor.CompileCode(codeString); // 编译任意字符串(片段校验)
await Editor.CompileAsync(); // 异步版本,避免卡 UI
CodeCompileResult 关键成员:
Success / AssemblyBytes / Errors(List<string>) / Warnings / Spans(结构化行列定位,配合 ShowCompileDiagnostics 用)。
波浪线具备动态失效逻辑:编译出错的行被编辑后约 0.3s 自动消失;未编辑行的标记跟随增删行正确平移;重新编译全量刷新。
6. 引用管理(运行期添加 DLL)
编译环境默认预置基础 BCL 十件套:
mscorlib / System / System.Core / System.Runtime / System.Collections / System.Linq / System.Console / System.Threading / System.IO / netstandard。
添加/移除引用
// 推荐:安装并引用一个用户 DLL。
// 会先复制到「exe 目录\References\」归档,再以副本加入编译环境,
// 保证补全元数据与运行期 CLR 绑定指向同一份稳定文件。
bool ok = Editor.InstallAndReferenceDll(@"D:\libs\Foo.dll");
// 底层 API(已有场景兼容)
Editor.AddReferenceFromFile(path); // 直接按路径引用
Editor.RemoveReference(mref); // 移除(ReferenceManager.References 里取)
Editor.References.References // 当前引用集合(做宿主列表 UI)
// 进阶
Editor.AddReferenceFromBytes(bytes, name); // 内存字节数组(内嵌 DLL/下载流)
Editor.ClearReferences(); // 清空(不会自动恢复默认)
Editor.ResetReferencesToDefaults(); // 重置回基础十件套
反馈
所有加载成功/失败信息通过事件推送,宿主可直接显示在状态栏或日志面板:
Editor.DiagnosticMessage += (s, msg) => statusText.Text = msg;
// 例:"✅ 已添加引用(DLL 已归档到 ...)"
// 例:"❌ 添加引用失败:Foo.dll — ..."(此时文件未被引用)
运行期解析约定
脚本运行期需要绑定自定义 DLL 时,CLR 按以下目录探测(都基于 exe 所在目录):
BaseDirectory\References\<name>.dll(引擎内置约定,配合 InstallAndReferenceDll 正好闭环)- 宿主自行注册
AppDomain.AssemblyResolve扩展其它目录(Demo 的 App.xaml.cs 有示例)
版本一致性提示:脚本 DLL 依赖第三方强命名程序集时,该 DLL 必须出现在 References 目录或与宿主已加载版本精确一致(必要时用 bindingRedirect 统一)。
7. 事件清单
Editor.CodeChanged += (s,e) => { }; // 内容变化(含用户输入与程序赋值)
Editor.DiagnosticMessage += (s,msg) => { };// 内部过程反馈(引用安装结果等)
Editor.CompileRequested += (s,e) => { }; // 右键菜单请求编译时触发
Editor.ScrollOffsetChanged += (s,e) => { };// 滚动偏移变化(滚动联动用)
Editor.ReferencesChanged += (s,e) => { }; // 引用集合变化
8. 高级 API
// Roslyn 深度访问(自建分析工具/跳转定义等)
SemanticModel? sm = Editor.GetSemanticModel();
SyntaxTree? st = Editor.GetSyntaxTree();
Document doc = Editor.Document; // AvalonEdit TextDocument 直读
// 补全数据直取(自绘补全 UI 场景)
CodeCompletionResult r = await Editor.GetCompletionsAsync(caretPosition);
List<CodeSignatureItem> sigs = await Editor.GetSignatureHelpAsync(position);
// 预热(消除首次补全冷启动;建议在窗口 Loaded 后 fire-and-forget)
_ = Editor.WarmupRoslynAsync();
// 光标/滚动控制
Editor.CaretIndex;
Editor.ScrollToLine(lineNo);
Editor.VerticalOffset / HorizontalOffset;
// 生命周期
Editor.Dispose(); // 释放 Roslyn 工作区资源
底层服务同样直接可达:Editor.Engine(CodeForgeEngine 门面)、Editor.CompletionService、Editor.EditorTextBox(AvalonEdit TextEditor 本体)。
9. 常见问题
Q:第一次补全慢?
Roslyn 冷启动需要加载元数据与 JIT,启动后调用一次 _ = editor.WarmupRoslynAsync(); 即可预热。
Q:补全里出现了不是引用里的类型? 三层来源审计会拦截绝大多数泄漏;若遇到可疑项请把补全截图和引用列表发给我们排查。
Q:DLL 加进去了,脚本运行报 FileNotFoundException?
说明运行期找不到依赖:确认该 DLL 已经过 InstallAndReferenceDll 归档到 exe 目录 References\ 下;它自身的第三方依赖也要一并放入。
Q:运行报 FileLoadException(0x80131040)? 强命名程序集版本不匹配。统一版本(升级引用包)或在宿主 App.config 增加 bindingRedirect。
Q:我想改默认欢迎文本?
设置 Code 属性即可覆盖;不设置就显示内置的引导示例。
10. 部署形态
10.1 单文件模式(默认,推荐)
构建时所有依赖 DLL(Roslyn 全家桶 / AvalonEdit / HandyControl 等约 34 个)已作为资源嵌入 CodeForge.dll,
运行期由内置解析器自动从资源加载 —— 宿主只需分发一个 CodeForge.dll。
- 自动生效:模块初始化器(ModuleInitializer)注册
AssemblyResolve,无需任何接线 - 兼容共存:exe 目录若同时存在物理 DLL,CLR 默认探测先行命中,不会重复加载
- 代价:CodeForge.dll 体积约 38MB
- XAML 注意事项:若宿主的 XAML 里直接使用了随包分发的控件/命名空间(例如
<hc:Window>这类 HandyControl 类型),BAML 解析发生得比"首次触碰 CodeForge 类型"更早——请在App静态构造函数里显式调用一次:
只在代码中使用控件的宿主可省略此行(模块初始化器自动生效)。static App() { CodeForge.CodeForgeRuntime.Initialize(); // 入口最早处,必须先于 InitializeComponent }
10.2 松散文件模式
如需剔除某些依赖(例如宿主已自带同版本的 HandyControl),删除 CodeForge.csproj 中
EmbedRuntimeDependencies 这个 Target 再编译即可回到传统的"引用目录"分发方式,
此时需把依赖 DLL 与 CodeForge.dll 一起拷贝到宿主。
| Product | Versions Compatible and additional computed target framework versions. |
|---|---|
| .NET Framework | net48 is compatible. net481 was computed. |
-
.NETFramework 4.8
- AvalonEdit (>= 6.3.0.90)
- HandyControl (>= 3.5.1)
- Microsoft.CodeAnalysis (>= 4.8.0)
- Microsoft.CodeAnalysis.CSharp (>= 4.8.0)
- Microsoft.CodeAnalysis.CSharp.Features (>= 4.8.0)
- Microsoft.CodeAnalysis.CSharp.Workspaces (>= 4.8.0)
- Microsoft.CodeAnalysis.Features (>= 4.8.0)
- Microsoft.CodeAnalysis.Workspaces.Common (>= 4.8.0)
- System.Composition (>= 8.0.0)
- System.Composition.Hosting (>= 8.0.0)
NuGet packages
This package is not used by any NuGet packages.
GitHub repositories
This package is not used by any popular GitHub repositories.
| Version | Downloads | Last Updated | |
|---|---|---|---|
| 1.0.0 | 102 | 8/27/2026 |