跑起来之后先看一眼你手上有什么。Known 的开源仓库刻意拆成"一个核心库 + 一个业务插件示范 + 三个宿主",边界非常干净:核心库不做业务、业务插件不选宿主、宿主不重复装配。这一页把每个目录谁负责什么讲清楚。
顶层目录
Known/
├── Known/ 核心 RCL(Razor 类库)
├── KnownApp/ 业务插件示例:装配自封装、页面、服务、数据
├── KnownWasm/ 纯前端宿主(BlazorWebAssembly)
├── KnownWeb/ 全栈一体宿主(ASP.NET Core + WASM hosted)
├── KnownWin/ 桌面宿主(WinForms + BlazorWebView)
├── Known.Cli/ dotnet 全局工具 known(项目脚手架,本文档暂不展开)
├── Known.CodeGen/ 代码骨架生成(供 Known.Cli 调用,暂不展开)
├── Known.Demo/ 在线示例集(组件详情页的"能改能跑"卡片)
└── Known.slnx 解决方案
Known/ · 核心 RCL
这是唯一的框架本体,也是所有其它工程唯一直接引用的 NuGet / ProjectReference。目录组织按能力切:
Known/
├── App.razor / App.razor.cs 根组件:<Router AppAssembly="Config.App.Assembly" AdditionalAssemblies="Config.Assemblies">
├── Config.cs 静态装配门面 + AppInfo / ClientOption / ServerOption / MenuGroup / TopAction
├── Attributes.cs [WebApi] / [Service] / [Menu] / [AppMenu] / [Column]
├── AuthProvider.cs IAuthProvider 契约 + 默认 AuthProvider(进程内用户 + 特性扫描装配)
├── ServiceProxy.cs DispatchProxy 生成的强类型 HTTP 门面
├── Entity.cs BaseEntity / EntityBase(Id、CreateBy/CreateTime、ModifyBy/ModifyTime…)
├── Result.cs Result / PagingCriteria / PagingResult<T>
├── Logger.cs 文件日志(按天 + 按大小滚动)
├── Components/ 112 个组件(AI / Base / Data / Devices / Feedback / Form / Layout / Media / Page)
│ ├── BaseComponent.cs 所有组件的基类:Class / Style / Disabled / Visible / UserAttributes + UI/Local 注入
│ ├── UIService.cs 全局消息门面:Toast / Notification / LoadingBar / Modal / Drawer
│ ├── LocalService.cs 本地化 + 主题 + 语言 + 密度 + 强调色
│ └── IconData.cs 内联 SVG 图标字典
├── Data/ ADO.NET 抽象 + 八种方言 + Schema 同步
│ ├── Database.cs Query / Execute / Page / Trans / Scalar / Schema 分部类
│ ├── DatabaseOption.cs AddSQLite / AddSQLServer / AddMySQL / AddPostgreSQL / AddOracle / AddDM / AddAccess
│ └── DbProvider.*.cs 各方言适配(分页语法、日期函数、布尔字面量)
├── Models/ 业务侧公用 DTO(UserInfo / LoginInfo / TraceLog / 各媒体状态…)
├── Cache/ EntityCache / PropertyCache(反射元数据缓存)
├── Extensions/ Type / Dictionary / DataTable / UI / Http 扩展
├── Helpers/ Snowflake / CsvHelper
└── Platforms/ AuthService / LanguageService / OnlineTracker / SysConfig / SysLanguage / DevLanguages / DevOnlineUsers / DevTraceLogs
Config.AddModule<T>() 是唯一入口,扫到的 [WebApi] [Service] [Menu] [AppMenu] [Table] 全部记在 Config 的静态列表里;AddKnownClient / AddKnownWeb / AddKnownDesktop 再据此生成 HTTP 代理、端点映射或本地 DI 绑定。核心库不做具体业务,Known/Platforms/AuthService.cs 那种默认实现只是给你参考、可以完全覆盖。
KnownApp/ · 业务插件示例
这是你写自己业务代码时该长成什么样的样板。它的核心不是页面,是 AppConfig.cs——把整个应用的启动装配沉在这里,暴露成一行 AddKnownApp(AppType) 给宿主调用:
namespace KnownApp;
public static class AppConfig
{
public static string AppId => "Known";
public static string AppName => "Known信息管理系统";
public static void AddKnownApp(this IServiceCollection services, AppType type)
{
var assembly = typeof(AppConfig).Assembly;
services.AddKnown(option =>
{
option.Id = AppId;
option.Name = AppName;
option.Type = type;
option.Assembly = assembly;
option.CreateTime = new DateTime(2026, 10, 1);
});
// 放到 AddKnown 后面,可以覆盖 AuthService 的默认实现
Config.AddModule(assembly);
// 菜单分组集中声明一次,页面 [Menu].Group 按 id 引用
Config.AddMenuGroup("components", "组件示例", icon: "package", order: 50);
Config.AddMenuGroup("system", "系统管理", icon: "sliders", order: 90);
// 组件菜单右侧挂徽标:数量取自 DemoCatalog(唯一真相源)
Config.AddMenuDecorator(item => { /* 按 Url 匹配组件一级页,写 item.Badge */ });
// 顶栏右上角自定义功能:Config.AddTopAction(...)
}
public static async Task SeedAsync(Database db) { /* 演示初始数据(幂等) */ }
}
三件事一次声明完:元信息(AppInfo)、模块扫描(Config.AddModule)、布局元数据(分组、装饰器、顶栏)。宿主不需要重复配置。
KnownApp/
├── AppConfig.cs 上面这段:AddKnownApp + SeedAsync
├── Apps/ 手机端页面:AppIndex.razor(登录后首页)
├── Pages/ 电脑端页面(Index / Login / Components/{每组一目录})
├── Services/ 业务服务实现(AuthService.cs 等,标记 [Service] 覆盖框架默认)
├── Demos/ 示例数据(组件在线示例的 seed 内容)
├── _Imports.razor(.cs) 命名空间批量导入,页面少写 using
└── wwwroot/ 本插件的静态资源 / 语言包 i18n/{tag}.json
Services/AuthService.cs 会带 [Service],Config.AddModule(assembly) 扫描时把它登记;AddKnownWeb 或 AddKnownDesktop 之后,IAuthService 从 DI 解析到的就是它、不再是框架默认——这就是"业务插件覆盖框架默认"的机制,也是 AddModule 要放在 AddKnown 之后的原因(AddKnown 内会先注册框架默认,业务侧后注册才能覆盖)。
KnownWasm/ · 纯前端宿主
只做引导,不放业务代码:
KnownWasm/
├── KnownWasm.csproj Sdk=Microsoft.NET.Sdk.BlazorWebAssembly,只引 KnownApp
├── Program.cs WebAssemblyHostBuilder + AddKnownApp + AddKnownClient
└── wwwroot/
├── index.html 加载占位 svg + blazor.webassembly.js + _content/Known/css|js
└── ... 静态资源
Program.cs 全文只有 5 行装配:
var builder = WebAssemblyHostBuilder.CreateDefault(args);
builder.RootComponents.Add<App>("#app");
builder.RootComponents.Add<HeadOutlet>("head::after");
builder.Services.AddKnownApp(AppType.Web);
builder.Services.AddKnownClient(o => o.BaseAddress = builder.HostEnvironment.BaseAddress);
await builder.Build().RunAsync();
KnownWeb/ · 全栈一体宿主
Sdk=Microsoft.NET.Sdk.Web,同时引用 KnownApp 与 KnownWasm(客户端就是被它托管的):
KnownWeb/
├── Program.cs 最小:AddApplication → Build → 一堆 Use → MapFallbackToFile
├── AppServer.cs AddApplication / UseApplication / MapWebApis / CookieAuthProvider
├── IotLogHub.cs (示例用)SignalR 中心:设备日志推送到 ConsoleLog 组件
├── IotLogWorker.cs (示例用)后台 worker:模拟设备日志广播
├── appsettings.json ConnString 等配置
├── wwwroot/ 服务端专属静态资源(服务端首屏 HTML 之外,客户端资源由 KnownWasm 出)
└── Logs/ 运行期文件日志(UseFileLogger)
AppServer.AddApplication 里做的三件事:AddKnownApp(AppType.Web) + AddKnownWeb(...) 挂数据库与文件日志 + Cookie 鉴权;UseApplication 里挂中间件、MapWebApis 扫端点、末尾 Services.UseDatabase(AppConfig.SeedAsync) 建表 + 灌种子。见 三种运行形态 的 Server 一节看完整代码。
KnownWin/ · 桌面宿主
Sdk=Microsoft.NET.Sdk.Razor + WinExe + UseWindowsForms,TFM net10.0-windows:
KnownWin/
├── Program.cs 手动 new ServiceCollection() + AddKnownApp(Desktop) + AddKnownDesktop + AddWindowsFormsBlazorWebView
├── MainForm.cs BlazorWebView.Dock=Fill / HostPage="wwwroot/index.html" / RootComponents.Add<App>("#app")
├── KnownWin.csproj WinExe / net10.0-windows / Costura.Fody IL 合并
├── FodyWeavers.xml Costura 配置
└── wwwroot/index.html 几乎与 WASM 版逐字相同,只是引导脚本换成 blazor.webview.js
Program.cs 尾部还多一步 provider.UseDatabase(AppConfig.SeedAsync)——桌面没有 WebApplication,得显式在 ServiceProvider 上调用建库 + 种子。
一句话记住的分层
Known/只提供能力:组件、装配、契约、数据、鉴权。业务代码不在这里。KnownApp/集中"我是谁 + 我要扫哪些程序集 + 我的菜单/顶栏长啥样":AddMyApp(AppType)一行封装。Known{Wasm|Web|Win}/只选运行形态:调用AddMyApp,加一个"运行形态入口"(AddKnownClient/AddKnownWeb/AddKnownDesktop),加鉴权与部署相关的中间件;不重复装配元数据。
这条分层保证:同一份 KnownApp razor 可以塞进三种宿主,业务代码不需要为运行形态做任何改动。
下一步
看懂结构之后,去 写第一个 CRUD 页面——亲手在 KnownApp 里加一份 [Table] 实体、[Service] 实现、[Menu] 页面,看 AddKnownApp 是怎么把它们一次扫进路由与菜单的。
扫码关注公众号
扫码加入 QQ 群