Asteroid.CodeBuilder
1.0.0
See the version list below for details.
dotnet add package Asteroid.CodeBuilder --version 1.0.0
NuGet\Install-Package Asteroid.CodeBuilder -Version 1.0.0
<PackageReference Include="Asteroid.CodeBuilder" Version="1.0.0" />
<PackageVersion Include="Asteroid.CodeBuilder" Version="1.0.0" />
<PackageReference Include="Asteroid.CodeBuilder" />
paket add Asteroid.CodeBuilder --version 1.0.0
#r "nuget: Asteroid.CodeBuilder, 1.0.0"
#:package Asteroid.CodeBuilder@1.0.0
#addin nuget:?package=Asteroid.CodeBuilder&version=1.0.0
#tool nuget:?package=Asteroid.CodeBuilder&version=1.0.0
Asteroid.CodeBuilder
C# 代码生成引擎 — 通过 Fluent API 和 DAG 节点树以程序化方式生成 C# 源代码。
概述
Asteroid.CodeBuilder 是一个基于 .NET 的代码生成框架,核心设计理念是用结构化的代码节点树来建模 C# 语法,通过声明式的 API 链式调用生成源代码文本。适用于 Roslyn Source Generator、代码重构工具、元编程等场景。
架构
┌─────────────────────────────────────────────────────────────┐
│ FileBuilder │
│ (文件级入口,持有 FileNode 根节点) │
└──────────────────────┬──────────────────────────────────────┘
│
┌──────────────────────▼──────────────────────────────────────┐
│ CodeNode System (DAG 节点树) │
│ ┌──────────┐ ┌──────────┐ ┌──────────┐ ┌─────────────┐ │
│ │ 声明节点 │ │ 表达式节点│ │ 语句节点 │ │ 组件节点 │ │
│ │ Class │ │ Literal │ │ If/Else │ │ Modifier │ │
│ │ Method │ │ Invoke │ │ For/Each │ │ Attribute │ │
│ │ Property │ │ New │ │ Try/Catch│ │ Param │ │
│ │ Enum │ │ Lambda │ │ Switch │ │ Constrain │ │
│ │ Namespace│ │ Linq │ │ Return │ │ Comment/Doc │ │
│ └──────────┘ └──────────┘ └──────────┘ └─────────────┘ │
└──────────────────────┬──────────────────────────────────────┘
│
┌──────────────────────▼──────────────────────────────────────┐
│ CodeNodeBuildContext (两阶段构建上下文) │
│ Phase1: Prepare → ShouldBuild 决策 │
│ Phase2: Build → 输出代码文本 │
└──────────────────────┬──────────────────────────────────────┘
│
┌──────────────────────▼──────────────────────────────────────┐
│ CodeTextBuilder (文本缓冲构建器) │
│ 缩进管理 / RAII 作用域 / 行控制 │
└─────────────────────────────────────────────────────────────┘
快速开始
1. 生成一个简单的类文件
using Asteroid.CodeBuilder;
using static Asteroid.CodeBuilder.Decl;
using static Asteroid.CodeBuilder.Exp;
var builder = FileBuilder.New("MyClass.cs");
builder.Root
.FileNamespace("MyApp.Core")
.Class("MyClass")
.AsPublic()
.DocSummary("核心业务类")
.Method("DoWork")
.AsPublic()
.Param(typeof(int), "x")
.With(Raw("Console.WriteLine(x)"));
string code = builder.ToCode(CancellationToken.None);
Console.WriteLine(code);
输出:
namespace MyApp.Core;
/// <summary>
/// 核心业务类
/// </summary>
public class MyClass
{
public void DoWork(int x) => Console.WriteLine(x);
}
2. 生成枚举
var builder = FileBuilder.New("Permissions.cs");
builder.Root
.FileNamespace("MyApp.Security")
.Enum("Permissions")
.AsPublic()
.Attribute(Exp.Ns.System.Qa("Flags"));
builder.Root.Enum("Permissions")
.Add("None").With(0)
.Add("Read").With(1)
.Add("Write").With(2)
.Add("Admin").With(7);
3. 生成带 if/else 的方法体
using static Asteroid.CodeBuilder.St;
using static Asteroid.CodeBuilder.Exp;
using static Asteroid.CodeBuilder.Decl;
var method = Method("GetStatus")
.AsPublic()
.Param(typeof(int), "code");
method.Body.Add(
If(GreaterThan(Id("code"), Literal(0)),
[
Return(String("positive"))
]));
method.Body.Add(
ElseIf(LessThan(Id("code"), Literal(0)),
[
Return(String("negative"))
]));
method.Body.Add(
Else([
Return(String("zero"))
]));
4. 复杂属性生成
// 自动属性 + 默认值
Decl.AutoProperty(typeof(int), "Count").AsPublic().With(Literal(10));
// ⮕ public int Count { get; set; } = 10;
// 只读表达式体属性
Decl.GetterProperty(typeof(int), "Value").AsPublic().With(Literal(42));
// ⮕ public int Value => 42;
核心概念
节点基类 (CodeNodeBase)
所有代码节点继承自 CodeNodeBase,通过 ChildNodes 属性定义子节点,支持两阶段生命周期:
| 阶段 | 方法 | 用途 |
|---|---|---|
| Prepare | OnPrepare |
初始化上下文 |
| Prepare | OnPrepareChild |
准备子节点 |
| Prepare | OnPrepared |
后处理 |
| Prepare | ShouldBuild |
决定是否构建 |
| Build | OnBuildStart |
构建前钩子 |
| Build | OnBuild |
核心构建逻辑 |
| Build | OnBuildEnd |
构建后钩子 |
核心规则:
- 节点结构是有向无环图(DAG),节点之间无父子引用
- 每个节点通过
ChildNodes声明依赖关系 - 两阶段确保最终输出内容按正确顺序组织
类型名系统
类型名可通过以下方式构建:
// 从 System.Type
var t1 = Exp.Type(typeof(List<int>));
// 从字符串
var t2 = Exp.Type("System.Collections.Generic.List<int>");
// 从 IdName(标识符)
var t3 = Exp.Id("myVar");
// 泛型类型
var t4 = Exp.Generic("List", [Exp.Type(typeof(int))]);
// QaName (Qualified Name) — 带命名空间的类型名
var t5 = Exp.Qa("System.Collections.Generic", "List");
// 利用预定义命名空间快捷方式
var t6 = Exp.Ns.System.Qa("StringBuilder");
// ⮕ System.Text.StringBuilder
// 隐式转换
TypeName tn = "MyClass";
ExpNode en = "someVariable"; // 隐式转为 Raw 表达式
预定义的命名空间快捷方式(Exp.Ns):
| 属性 | 值 |
|---|---|
Exp.Ns.System |
System |
Exp.Ns.SystemCollectionsGeneric |
System.Collections.Generic |
Exp.Ns.SystemIO |
System.IO |
Exp.Ns.SystemLinq |
System.Linq |
Exp.Ns.SystemNetHttp |
System.Net.Http |
Exp.Ns.SystemThreading |
System.Threading |
Exp.Ns.SystemThreadingTasks |
System.Threading.Tasks |
Exp.Ns.SystemDiagnosticsCodeAnalysis |
System.Diagnostics.CodeAnalysis |
文件节点 (FileNode)
文件节点支持:
var builder = FileBuilder.New("Service.cs", "Copyright 2024");
builder.Root
.FileNamespace("App") // 文件作用域命名空间
.Using(Exp.Ns.SystemLinq) // using 指令
.UsingStatic(Exp.Ns.System.Qa("Console"))// using static 指令
.NullableEnable() // #nullable enable
.GlobalUsing(Exp.Ns.SystemCollectionsGeneric) // global using
.WarningDisable_RequireNewFlag() // #pragma warning disable CS0108
.Class("Service").AsPublic();
API 参考
声明节点工厂 (Decl)
所有声明类型:
| 方法 | 生成代码 |
|---|---|
Decl.Class("MyClass") |
class MyClass { ... } |
Decl.Record("MyRecord") |
record MyRecord { ... } |
Decl.Struct("MyStruct") |
struct MyStruct { ... } |
Decl.Interface("IMyInterface") |
interface IMyInterface { ... } |
Decl.Enum("MyEnum") |
enum MyEnum { ... } |
Decl.Delegate(type, name) |
delegate type Name(...); |
Decl.Event(type, name) |
event type name; |
Decl.Indexer(type) |
type this[...] { get; set; } |
方法变体:
| 方法 | 生成代码 |
|---|---|
Decl.Method(type, "DoWork") |
type DoWork(...) { ... } |
Decl.Method("DoWork") |
void DoWork(...) { ... } |
Decl.Constructor("MyClass") |
MyClass(...) { ... } |
Decl.Destructor("MyClass") |
~MyClass() { ... } |
Decl.Operator(type, "op") |
static type operator op(...) { ... } |
Decl.ImplicitConverter(type, param) |
static implicit operator type(param) { ... } |
Decl.ExplicitConverter(type, param) |
static explicit operator type(param) { ... } |
属性变体:
| 方法 | 生成代码 |
|---|---|
Decl.Property(type, "Name") |
type Name { get; set; } |
Decl.AutoProperty(type, "Name") |
type Name { get; set; } = default; |
Decl.GetterProperty(type, "Name") |
type Name => expr; |
Decl.GetterAutoProperty(type, "Name") |
type Name { get; } = default; |
特殊方法:
| 方法 | 生成代码 |
|---|---|
Decl.Method_Deconstruct(params) |
void Deconstruct(...) { ... } |
Decl.Method_Override_Equals(type) |
public override bool Equals(object obj) |
Decl.Method_Override_GetHashCode(values) |
public override int GetHashCode() |
Decl.Method_Override_ToString(exp) |
public override string ToString() |
链式修饰符(扩展方法):
| 方法 | 作用 |
|---|---|
.AsPublic() / .AsPrivate() / .AsInternal() |
访问修饰符 |
.AsProtected() / .AsProtectedInternal() / .AsPrivateProtected() / .AsFile() |
访问修饰符 |
.AsStatic() / .AsPartial() / .AsOverride() |
类型修饰符 |
.AsAbstract() / .AsVirtual() / .AsSealed() |
行为修饰符 |
.AsReadonly() / .AsAsync() / .AsNew() |
其他修饰符 |
.AsUnsafe() / .AsExtern() / .AsImplicit() / .AsExplicit() |
特殊修饰符 |
表达式工厂 (Exp)
字面量
| 方法 | 生成代码 |
|---|---|
Exp.Literal(42) |
42 |
Exp.Literal(3.14f) |
3.14f |
Exp.Literal(true) |
true |
Exp.Literal('x') |
'x' |
Exp.String("hello") |
"hello" |
Exp.VerbatimString("a\\b") |
@"a\\b" |
Exp.RawString("multi\\nline") |
"""multi\\nline""" |
Exp.Null |
null |
Exp.Default |
default |
标识符与访问
| 方法 | 生成代码 |
|---|---|
Exp.Id("x") |
x |
Exp.Id("class") |
@class(关键字自动转义) |
Exp.Raw("x + y") |
x + y(原始文本) |
Exp.Empty |
(空,不输出) |
obj.Acc(member) |
obj.member |
obj.NAcc(member) |
obj?.member |
obj.PAcc(member) |
obj->member |
调用与索引
| 方法 | 生成代码 |
|---|---|
Exp.Invoke(f) |
f() |
Exp.Invoke(f, [a, b]) |
f(a, b) |
obj.Invoke(m, args) |
obj.m(args) |
obj.NInvoke(m, args) |
obj?.m(args) |
obj.PInvoke(m, args) |
obj->m(args) |
Exp.Index(arr, 0) |
arr[0] |
Exp.NIndex(arr, 0) |
arr?[0] |
一元运算符
| 方法 | 生成代码 |
|---|---|
Exp.Positive(x) |
+x |
Exp.Negative(x) |
-x |
Exp.Not(flag) |
!flag |
Exp.Bit_Not(x) |
~x |
Exp.PreInc(x) |
++x |
Exp.PostInc(x) |
x++ |
Exp.PreDec(x) |
--x |
Exp.PostDec(x) |
x-- |
Exp.AddressOf(x) |
&x |
Exp.PointerDeref(x) |
*x |
二元运算符
| 方法 | 生成代码 |
|---|---|
Exp.Plus(a, b) |
a + b |
Exp.Minus(a, b) |
a - b |
Exp.Multiply(a, b) |
a * b |
Exp.Divide(a, b) |
a / b |
Exp.Modulo(a, b) |
a % b |
Exp.Equal(a, b) |
a == b |
Exp.NotEqual(a, b) |
a != b |
Exp.LessThan(a, b) |
a < b |
Exp.GreaterThan(a, b) |
a > b |
Exp.LessThanOrEqual(a, b) |
a <= b |
Exp.GreaterThanOrEqual(a, b) |
a >= b |
Exp.And(a, b) |
a && b |
Exp.Or(a, b) |
a \|\| b |
Exp.BitAnd(a, b) |
a & b |
Exp.BitOr(a, b) |
a \| b |
Exp.BitXor(a, b) |
a ^ b |
Exp.LShift(a, b) |
a << b |
Exp.RShift(a, b) |
a >> b |
Exp.URShift(a, b) |
a >>> b |
Exp.NC(a, b) |
a ?? b |
Exp.NF(exp) |
exp!(null 包容) |
Exp.Sum([a, b, c]) |
a + b + c(链式求和) |
Exp.Product([a, b, c]) |
a * b * c(链式求积) |
赋值运算符
| 方法 | 生成代码 |
|---|---|
Exp.Assign(a, b) |
a = b |
Exp.PlusAssign(a, b) |
a += b |
Exp.MinusAssign(a, b) |
a -= b |
Exp.MultiplyAssign(a, b) |
a *= b |
Exp.DivideAssign(a, b) |
a /= b |
Exp.ModuloAssign(a, b) |
a %= b |
Exp.AndAssign(a, b) |
a &= b |
Exp.OrAssign(a, b) |
a \|= b |
Exp.XorAssign(a, b) |
a ^= b |
Exp.LShiftAssign(a, b) |
a <<= b |
Exp.RShiftAssign(a, b) |
a >>= b |
Exp.URShiftAssign(a, b) |
a >>>= b |
Exp.NCAssign(a, b) |
a ??= b |
类型操作
| 方法 | 生成代码 |
|---|---|
Exp.Cast(x, type) |
(type)x |
Exp.As(x, type) |
x as type |
Exp.TypeOf(type) |
typeof(type) |
Exp.NameOf(x) |
nameof(x) |
Exp.SizeOf(type) |
sizeof(type) |
Exp.DefaultOf(type) |
default(type) |
三目与括号
| 方法 | 生成代码 |
|---|---|
Exp.Ternary(cond, a, b) |
cond ? a : b |
Exp.P(exp) |
(exp) |
Exp.Range(a, b) |
a..b |
Exp.Spread(x) |
..x |
Exp.FromEnd(x) |
^x |
Exp.Await(task) |
await task |
Checked / Unchecked
| 方法 | 生成代码 |
|---|---|
Exp.Checked(exp) |
checked(exp) |
Exp.Unchecked(exp) |
unchecked(exp) |
变量声明表达式
| 方法 | 生成代码 |
|---|---|
Exp.DeclVar(type, name) |
type name |
Exp.DeclVar("x") |
var x |
Exp.DeclDeconstructVar(["x","y"]) |
var (x, y) |
Lambda
| 方法 | 生成代码 |
|---|---|
Exp.Lambda(param, body) |
param => body |
Exp.Lambda("x", x.Acc("Name")) |
x => x.Name |
Lambda(...).AsStatic() |
static x => ... |
对象创建
| 方法 | 生成代码 |
|---|---|
Exp.New(type) |
new type() |
Exp.NewAnonymous() |
new { ... } |
Exp.NewArray(type, rank) |
new type[...] { ... } |
Exp.NewAnonymousArray() |
new[] { ... } |
Exp.StackAlloc(type, len) |
stackalloc type[len] |
Exp.With(source, inits) |
source with { ... } |
Exp.KVInit(key, value) |
{ key, value } |
变量声明与初始化
var decl = Exp.DeclVar(typeof(int), "count");
// ⮕ int count
var assign = decl.Assign(Literal(42));
// ⮕ int count = 42
Throw 表达式
| 方法 | 生成代码 |
|---|---|
Exp.Throw(ex) |
throw ex; |
Exp.Throw_NotSupport() |
throw new NotSupportedException(); |
Exp.Throw_NotImplemented() |
throw new NotImplementedException(); |
模式匹配
| 方法 | 生成代码 |
|---|---|
Exp.Is(exp, pattern) |
exp is pattern |
Exp.Is(exp, type, name) |
exp is type name |
Exp.IsNotNull(exp, name) |
exp is { } name |
Exp.IsNot(exp, pattern) |
exp is not pattern |
Exp.PNot(exp) |
not exp |
Exp.POr(a, b) |
a or b |
Exp.PAnd(a, b) |
a and b |
Exp.When(pattern, cond) |
pattern when cond |
Exp.PropertyPattern(matches) |
{ Prop: pattern } |
Exp.Switch(val, arms) |
val switch { arms } |
Exp.SwitchArm(pattern, exp) |
pattern => exp |
集合与元组
| 方法 | 生成代码 |
|---|---|
Exp.Collection([a, b]) |
[a, b] |
Exp.Tuple([a, b]) |
(a, b) |
Exp.Init([a, b]) |
{ a, b } |
参数与引用
| 方法 | 生成代码 |
|---|---|
Exp.Param(type, name) |
type name |
Exp.Arg(exp) |
exp |
Exp.NamedArg("x", exp) |
x: exp |
Exp.Arg_Ref(exp) |
ref exp |
Param(...).WithRef() |
ref type name |
Param(...).WithOut() |
out type name |
Param(...).WithIn() |
in type name |
Param(...).WithThis() |
this type name |
LINQ 查询表达式
Exp.Linq()
.From("p", Exp.Id("people"))
.Where(Exp.GreaterThan(Exp.Id("p").Acc("Age"), Literal(18)))
.Select(Exp.Id("p").Acc("Name"));
// ⮕ from p in people
// where p.Age > 18
// select p.Name
| 方法 | 生成代码 |
|---|---|
Exp.Linq() |
LINQ 表达式组容器 |
Exp.LinqFrom(var, src) |
from var in src |
Exp.LinqLet(var, val) |
let var = val |
Exp.LinqWhere(cond) |
where cond |
Exp.LinqSelect(result) |
select result |
Exp.LinqGroupBy(var, key, into) |
group var by key into g |
Exp.LinqOrderBy(val) |
orderby val ascending |
Exp.LinqJoin(...) |
join ... in ... on ... equals ... |
语句工厂 (St)
基本语句
| 方法 | 生成代码 |
|---|---|
St.Line(exp) |
exp; |
St.Comment("text") |
// text |
St.EmptyLine |
(空行) |
St.Block([...]) |
{ ... } |
条件语句
| 方法 | 生成代码 |
|---|---|
St.If(cond, [stmts]) |
if (cond) { ... } |
St.ElseIf(cond, [stmts]) |
else if (cond) { ... } |
St.Else([stmts]) |
else { ... } |
循环语句
| 方法 | 生成代码 |
|---|---|
St.While(cond) |
while (cond) { ... } |
St.For(init, cond, step) |
for (init; cond; step) { ... } |
St.ForN(var, max) |
for (int i = 0; i < max; i++) { ... } |
St.Foreach(type, name, coll) |
foreach (type name in coll) { ... } |
St.Foreach(name, coll) |
foreach (var name in coll) { ... } |
St.DoWhile(cond) |
do { ... } while (cond); |
Switch 语句
| 方法 | 生成代码 |
|---|---|
St.Switch(cond) |
switch (cond) { ... } |
Switch.Case(exp, [stmts]) |
case exp: ... |
Switch.DefaultCase([stmts]) |
default: ... |
Try/Catch 语句
| 方法 | 生成代码 |
|---|---|
St.Try([stmts]) |
try { ... } |
St.Catch([stmts]) |
catch { ... } |
St.Catch(varDecl, when, [stmts]) |
catch (varDecl) when (cond) { ... } |
St.Finally([stmts]) |
finally { ... } |
其他语句
| 方法 | 生成代码 |
|---|---|
St.Section([stmts]) |
隐式区段 |
St.Region("name", [stmts]) |
#region name ... #endregion |
St.Using(exp, [stmts]) |
using (exp) { ... } |
St.UsingVar(decl, exp) |
using var = exp; |
St.Fixed(decl, exp, [stmts]) |
fixed (decl = exp) { ... } |
St.Unsafe([stmts]) |
unsafe { ... } |
St.Checked([stmts]) |
checked { ... } |
组件节点
修饰符
所有声明节点可通过 .AsXxx() 链式设置修饰符。自动处理修饰符冲突(如 AsPublic() 会移除其他访问修饰符)。
支持的修饰符:
- 访问级别:
public/private/internal/protected/protected internal/private protected/file - 类型:
static/partial/abstract/virtual/override/sealed - 成员:
readonly/const/volatile/async/new/unsafe/extern - 属性:
required/ref
特性 (Attribute)
cls.Attribute(Exp.Ns.System.Qa("Serializable"));
// ⮕ [Serializable]
cls.Attribute(Exp.Ns.System.Qa("Obsolete"));
// ⮕ [Obsolete]
// 带参数的特性
attr.Arg(Exp.String("Use NewMethod instead"));
// ⮕ [Obsolete("Use NewMethod instead")]
文档注释
Decl.Class("MyClass").AsPublic()
.DocSummary("A class that does things")
.Doc("Use <see cref=\"DoWork\"/> to start");
// ⮕ /// <summary>
// /// A class that does things
// /// </summary>
// /// Use <see cref="DoWork"/> to start
Doc 帮助类:
| 方法 | 输出 |
|---|---|
Doc.Para("text") |
<para>text</para> |
Doc.SeeCref("MyClass") |
<see cref="MyClass"/> |
Doc.SeeHref("link", "text") |
<see href="link">text</see> |
Doc.SeeLangword("true") |
<see langword="true"/> |
泛型约束
cls.Param(typeof(T), "T");
cls.Constrain("T").With(Exp.Id("class", false));
// ⮕ where T : class
继承列表
cls.Inherit("IMyInterface");
cls.Inherit("BaseClass");
// ⮕ class MyClass : BaseClass, IMyInterface
节区 (Section)
var cls = Decl.Class("MyClass").AsPublic();
var ctorSection = cls.Section("#region Constructors");
ctorSection.Constructor("MyClass").AsPublic();
文件预处理器指令
| 方法 | 生成代码 |
|---|---|
Preprocessor.Nullable_Enable() |
#nullable enable |
Preprocessor.Nullable_Disable() |
#nullable disable |
Preprocessor.Nullable_Restore() |
#nullable restore |
Preprocessor.Pragma_WarningDisable("CS0108") |
#pragma warning disable CS0108 |
Preprocessor.Define("DEBUG") |
#define DEBUG |
Preprocessor.Undefine("DEBUG") |
#undef DEBUG |
Preprocessor.If(cond) |
#if cond |
Preprocessor.Elif(cond) |
#elif cond |
Preprocessor.Else() |
#else |
Preprocessor.EndIf() |
#endif |
CodeTextBuilder
底层文本构建器,供高级定制使用:
| 成员 | 用途 |
|---|---|
Append(text) |
追加文本 |
AppendLine(text) |
追加文本并换行 |
AppendNodes(nodes) |
追加子节点列表 |
IndentLevel |
获取/设置缩进级别 |
Indenter |
缩进字符串(默认 \t) |
NewLine |
换行符(默认 \n) |
NewIndentScope() |
RAII 缩进作用域 |
NewSetIndentScope(level) |
RAII 固定缩进作用域 |
NewParenthesesScope(...) |
RAII 括号作用域 |
NewCurlyBracesScope(...) |
RAII 花括号作用域 |
NewBracketsScope(...) |
RAII 方括号作用域 |
StartLine() / EndLine() |
行控制 |
ImplicitUsings
启用 Option.EnableImplicitUsings 后,自动注入以下命名空间:
SystemSystem.IOSystem.Collections.GenericSystem.LinqSystem.Net.HttpSystem.ThreadingSystem.Threading.Tasks
完整示例
生成一个完整的 .cs 文件
using Asteroid.CodeBuilder;
using static Asteroid.CodeBuilder.Decl;
using static Asteroid.CodeBuilder.Exp;
using static Asteroid.CodeBuilder.St;
public string GenerateServiceFile()
{
var builder = FileBuilder.New("UserService.cs", "Auto-generated");
var root = builder.Root;
// 文件头
root.FileNamespace("MyApp.Services");
root.Using(Exp.Ns.SystemLinq);
root.Class("UserService").AsPublic()
.DocSummary("用户服务")
// 字段
.Field(typeof(List<User>), "_users")
.AsPrivate()
.With(New(Exp.Generic("List", [Exp.Type(typeof(User))])))
// 构造函数
.Constructor("UserService")
.AsPublic()
// 属性
.AutoProperty(typeof(int), "Count")
.AsPublic()
// 方法
.Method("GetUser")
.AsPublic()
.Param(typeof(int), "id")
.With(Ternary(Equal(Id("id"), Literal(0)),
Exp.Null,
Exp.Invoke(Exp.Id("_users"), "FirstOrDefault", [Exp.Lambda("u", u =>
Exp.Equal(u.Acc("Id"), Id("id")))])));
return builder.ToCode(CancellationToken.None);
}
使用方法体填充复杂逻辑
var method = Decl.Method("ProcessData")
.AsPublic()
.Param(typeof(int), "value");
method.Body.Add(If(GreaterThan(Id("value"), Literal(100)),
[
St.Line(Exp.Invoke("Log", Exp.String("Large value"))),
Return(Id("value"))
]));
method.Body.Add(
St.Try([
St.Line(Invoke(Id("Process"), Id("value"))),
]));
method.Body.Add(
St.Catch(Exp.DeclVar(typeof(Exception), "ex"), [
St.Line(Invoke("LogError", Id("ex"))),
]));
method.Body.Add(
St.Finally([
St.Line(Invoke(Id("Cleanup"))),
]));
安装
通过 NuGet 安装:
dotnet add package Asteroid.CodeBuilder
或直接引用项目:
<ProjectReference Include="..\CodeBuilder\Asteroid.CodeBuilder.csproj" />
Exp.Lambda(p, e) |
p => e |
|---|---|
Exp.Plus(a, b) |
a + b |
Exp.Ternary(c, t, f) |
c ? t : f |
Exp.Is(e, p) |
e is p |
Exp.Switch(v, arms) |
v switch { arms } |
Exp.Throw(e) |
throw e |
语句工厂 (St)
| 方法 | 生成代码 |
|---|---|
St.Line(exp) |
exp; |
St.Block(stmts) |
{ stmts } |
St.If(cond, stmts) |
if (cond) { stmts } |
St.ElseIf(cond, stmts) |
else if (cond) { stmts } |
St.Else(stmts) |
else { stmts } |
St.While(cond, stmts) |
while (cond) { stmts } |
St.For(init, cond, step) |
for (init; cond; step) { ... } |
St.Foreach(type, n, col) |
foreach (type n in col) { ... } |
St.Try(stmts) |
try { stmts } |
St.Catch(var, when, stmts) |
catch (var) when (when) { stmts } |
St.Finally(stmts) |
finally { stmts } |
St.Return(exp) |
return exp; |
St.Switch(cond, cases) |
switch (cond) { cases } |
项目依赖
- .NET 10
- 无第三方依赖
在 Source Generator 中使用
[Generator]
public class MyGenerator : IIncrementalGenerator
{
public void Initialize(IncrementalGeneratorInitializationContext ctx)
{
ctx.RegisterPostInitializationOutput(static context =>
{
var builder = FileBuilder.New("GeneratedClass.cs");
builder.Root
.FileNamespace("MyNamespace")
.Class("GeneratedClass")
.AsPublic()
.Method("Hello")
.AsPublic()
.AsStatic()
.With(Raw("Console.WriteLine(\"Hello from source generator!\")"));
context.AddSource("GeneratedClass.g.cs", builder.ToCode(CancellationToken.None));
});
}
}
许可证
MIT
| Product | Versions Compatible and additional computed target framework versions. |
|---|---|
| .NET | net10.0 is compatible. net10.0-android was computed. net10.0-browser was computed. net10.0-ios was computed. net10.0-maccatalyst was computed. net10.0-macos was computed. net10.0-tvos was computed. net10.0-windows was computed. |
-
net10.0
- No dependencies.
NuGet packages
This package is not used by any NuGet packages.
GitHub repositories
This package is not used by any popular GitHub repositories.