跳到主要内容

C# 标准库

EasyBot 将 C# 标准库(System 命名空间)映射到了插件运行环境中的 dotnet 命名空间。通过 dotnet 命名空间,你可以访问 System 命名空间的所有内容。

基本用法

控制台输出

// 对应 System.Console.WriteLine
dotnet.Console.WriteLine("Hello World!");

// 格式化输出
dotnet.Console.WriteLine("用户 {0} 发送了消息: {1}", userName, message);

// 输出到错误流
dotnet.logger.error.WriteLine("这是一个错误消息");

字符串操作

// 对应 System.String 的静态方法
const result = dotnet.String.Format("Hello {0}!", "World");
const isEmpty = dotnet.String.IsNullOrEmpty(someString);
const isWhitespace = dotnet.String.IsNullOrWhiteSpace(someString);

// 字符串连接
const joined = dotnet.String.Join(", ", ["apple", "banana", "orange"]);

数学运算

// 对应 System.Math
const max = dotnet.Math.Max(10, 20);
const min = dotnet.Math.Min(10, 20);
const abs = dotnet.Math.Abs(-5);
const sqrt = dotnet.Math.Sqrt(16);
const pow = dotnet.Math.Pow(2, 3);
const round = dotnet.Math.Round(3.14159, 2);

日期时间

// 对应 System.DateTime
const now = dotnet.DateTime.Now;
const utcNow = dotnet.DateTime.UtcNow;
const today = dotnet.DateTime.Today;

// 创建特定日期
const specificDate = new dotnet.DateTime(2024, 1, 1);

// 日期格式化
const formatted = now.ToString("yyyy-MM-dd HH:mm:ss");

核心接口

IList<T> - 列表接口

表示可按索引访问的对象的非泛型集合。

interface IList<T> {
readonly Count: number; // 集合中元素的数量
readonly IsReadOnly: boolean; // 是否为只读集合

// 索引访问
get(index: number): T;
set(index: number, value: T): void;

// 集合操作
Add(item: T): void;
Clear(): void;
Contains(item: T): boolean;
CopyTo(array: T[], arrayIndex: number): void;
IndexOf(item: T): number;
Insert(index: number, item: T): void;
Remove(item: T): boolean;
RemoveAt(index: number): void;
}

示例:

// 使用 IList 接口的集合
const list = new dotnet.List(); // 假设有这样的实现

// 添加元素
list.Add("item1");
list.Add("item2");

// 访问元素
const firstItem = list.get(0);
list.set(1, "newItem");

// 检查和查找
const count = list.Count;
const hasItem = list.Contains("item1");
const index = list.IndexOf("item1");

// 移除元素
list.Remove("item1");
list.RemoveAt(0);

IEnumerator<T> - 枚举器接口

支持对泛型集合的简单迭代。

interface IEnumerator<T> {
Current: T; // 当前元素
MoveNext(): boolean; // 移动到下一个元素
Reset(): void; // 重置枚举器
}

示例:

// 使用枚举器遍历集合
const enumerator = collection.GetEnumerator();
while (enumerator.MoveNext()) {
const current = enumerator.Current;
logger.info(current);
}
enumerator.Reset(); // 重置到开始位置

IDisposable - 资源释放接口

提供一种机制来释放未托管资源。

interface IDisposable {
Dispose(): void; // 释放资源
}

示例:

// 使用 using 模式(如果支持)
const resource = new dotnet.SomeResource();
try {
// 使用资源
resource.DoSomething();
} finally {
// 确保资源被释放
resource.Dispose();
}

网络相关类型

IPEndPoint - 网络终结点

表示网络终结点,包含 IP 地址和端口信息。

interface IPEndPoint {
MaxPort: number; // 最大端口号
MinPort: number; // 最小端口号
Address: IPAddress; // IP地址对象
readonly AddressFamily: any; // 地址族类型
Port: number; // 端口号

// 方法
Create(socketAddress: SocketAddress): any;
Equals(comparand: any | null): boolean;
GetHashCode(): number;
Parse(s: string): IPEndPoint;
Serialize(): SocketAddress;
ToString(): string;
TryParse(s: string, result: IPEndPoint | null): boolean;
}

示例:

// 解析 IP 终结点
const endpoint = dotnet.IPEndPoint.Parse("127.0.0.1:8080");
logger.info(`地址: ${endpoint.Address}, 端口: ${endpoint.Port}`);

// 创建新的终结点
const newEndpoint = new dotnet.IPEndPoint(dotnet.IPAddress.Parse("192.168.1.1"), 3000);

// 转换为字符串
const endpointString = endpoint.ToString(); // "127.0.0.1:8080"

常用功能示例

文件操作

// 对应 System.IO.File
const exists = dotnet.File.Exists("config.json");
const content = dotnet.File.ReadAllText("config.json");
dotnet.File.WriteAllText("output.txt", "Hello World!");

// 对应 System.IO.Path
const fileName = dotnet.Path.GetFileName("/path/to/file.txt");
const extension = dotnet.Path.GetExtension("file.txt");
const combined = dotnet.Path.Combine("folder", "subfolder", "file.txt");

环境信息

// 对应 System.Environment
const machineName = dotnet.Environment.MachineName;
const userName = dotnet.Environment.UserName;
const osVersion = dotnet.Environment.OSVersion;
const currentDirectory = dotnet.Environment.CurrentDirectory;

// 环境变量
const pathVar = dotnet.Environment.GetEnvironmentVariable("PATH");
dotnet.Environment.SetEnvironmentVariable("MY_VAR", "value");

类型转换

// 对应 System.Convert
const intValue = dotnet.Convert.ToInt32("123");
const doubleValue = dotnet.Convert.ToDouble("3.14");
const boolValue = dotnet.Convert.ToBoolean("true");
const base64 = dotnet.Convert.ToBase64String(byteArray);
const bytes = dotnet.Convert.FromBase64String(base64String);

GUID 操作

// 对应 System.Guid
const newGuid = dotnet.Guid.NewGuid();
const emptyGuid = dotnet.Guid.Empty;
const guidFromString = dotnet.Guid.Parse("12345678-1234-1234-1234-123456789abc");

logger.info(newGuid.ToString()); // 输出 GUID 字符串

正则表达式

// 对应 System.Text.RegularExpressions.Regex
const regex = new dotnet.Regex(@"\d+");
const isMatch = regex.IsMatch("abc123def");
const match = regex.Match("abc123def");
const matches = regex.Matches("123 and 456");

// 替换
const result = dotnet.Regex.Replace("abc123def", @"\d+", "XXX");

实际应用示例

配置文件处理

function loadConfig(configPath) {
try {
if (!dotnet.File.Exists(configPath)) {
logger.warning("配置文件不存在: {0}", configPath);
return getDefaultConfig();
}

const content = dotnet.File.ReadAllText(configPath);
const config = JSON.parse(content);

logger.info("成功加载配置文件: {0}", configPath);
return config;
} catch (error) {
logger.error("加载配置文件失败: {0}", error.message);
return getDefaultConfig();
}
}

function saveConfig(config, configPath) {
try {
const content = JSON.stringify(config, null, 2);
dotnet.File.WriteAllText(configPath, content);
logger.info("配置文件已保存: {0}", configPath);
} catch (error) {
logger.error("保存配置文件失败: {0}", error.message);
}
}

数据验证

function validateInput(input) {
// 检查是否为空
if (dotnet.String.IsNullOrWhiteSpace(input)) {
return { valid: false, message: "输入不能为空" };
}

// 长度检查
if (input.length > 100) {
return { valid: false, message: "输入长度不能超过100字符" };
}

// 正则表达式验证
const regex = new dotnet.Regex(@"^[a-zA-Z0-9_]+$");
if (!regex.IsMatch(input)) {
return { valid: false, message: "输入只能包含字母、数字和下划线" };
}

return { valid: true, message: "验证通过" };
}

时间处理

function formatTimeAgo(dateTime) {
const now = dotnet.DateTime.Now;
const timeSpan = now.Subtract(dateTime);

if (timeSpan.TotalDays >= 1) {
return dotnet.String.Format("{0} 天前", dotnet.Math.Floor(timeSpan.TotalDays));
} else if (timeSpan.TotalHours >= 1) {
return dotnet.String.Format("{0} 小时前", dotnet.Math.Floor(timeSpan.TotalHours));
} else if (timeSpan.TotalMinutes >= 1) {
return dotnet.String.Format("{0} 分钟前", dotnet.Math.Floor(timeSpan.TotalMinutes));
} else {
return "刚刚";
}
}

function scheduleTask(delayMinutes, callback) {
const executeTime = dotnet.DateTime.Now.AddMinutes(delayMinutes);
logger.info("任务将在 {0} 执行", executeTime.ToString("yyyy-MM-dd HH:mm:ss"));

// 使用定时器延迟执行
setTimeout(() => {
logger.info("执行定时任务");
callback();
}, delayMinutes * 60 * 1000);
}

网络工具

function parseEndpoint(endpointString) {
try {
const endpoint = dotnet.IPEndPoint.Parse(endpointString);
return {
address: endpoint.Address.ToString(),
port: endpoint.Port,
valid: true
};
} catch (error) {
return {
address: null,
port: null,
valid: false,
error: error.message
};
}
}

function isValidPort(port) {
return port >= dotnet.IPEndPoint.MinPort && port <= dotnet.IPEndPoint.MaxPort;
}

注意事项

  1. 命名空间映射: 所有 System 命名空间的内容都通过 dotnet 前缀访问
  2. 类型转换: JavaScript 和 C# 之间的类型转换是自动的,但要注意精度问题
  3. 异常处理: C# 异常会被转换为 JavaScript 异常,建议使用 try-catch
  4. 内存管理: 实现了 IDisposable 的对象应该及时调用 Dispose() 方法
  5. 性能考虑: 频繁调用 .NET 方法可能有性能开销

参考文档

相关文档