internal static class InternalUtilities
{
public delegate T ValueDelegate();
public class KeepRunningContainer
{
public bool KeepRunning = true;
}
public delegate TOut CultureTry(CultureInfo ci);
public static T[] SubArray(T[] data, int start, int end)
{
T[] array = new T[end - start + 1];
Array.Copy(data, start, array, 0, end + 1);
return array;
}
public static void FillArray(T[] data, T value)
{
for (int i = 0; i < data.Length; i++)
{
data[i] = value;
}
}
public static T[] Flip(T[] data)
{
T[] array = new T[data.Length];
for (int i = 0; i < data.Length; i++)
{
array[data.Length - i - 1] = data[i];
}
return array;
}
public static void EnsureCapacity(List list, int capacity) where T : class
{
if (list.Count <= capacity)
{
list.AddRange(new T[capacity - list.Count + 1]);
}
}
[Conditional("DEBUG")]
public static void OutputMyInfo(object o)
{
}
[Conditional("DEBUG")]
public static void OutputMyInfo(object o, bool fields)
{
}
[Conditional("DEBUG")]
public static void OutputMyInfo(object o, string offset)
{
}
[Conditional("DEBUG")]
public static void OutputMyInfo(object o, string offset, bool fields)
{
if (o == null)
{
Console.WriteLine("__NULL__");
return;
}
if (o is IEnumerable && !(o is string))
{
int num = 0;
foreach (object item in o as IEnumerable)
{
_ = item;
Console.WriteLine(offset + "[" + num++ + "] : ");
}
}
else if (o is IDictionary)
{
foreach (object key in (o as IDictionary).Keys)
{
Console.WriteLine(offset + key.ToString() + " :");
}
}
if (o is Array)
{
int num2 = 0;
{
foreach (object item2 in o as Array)
{
_ = item2;
Console.WriteLine(offset + "[" + num2++ + "] :");
}
return;
}
}
if (o is string)
{
Console.Write(offset);
Console.WriteLine(o);
}
else if ((object)o.GetType().Assembly == Assembly.GetExecutingAssembly() && !o.GetType().IsEnum)
{
PropertyInfo[] properties = o.GetType().GetProperties();
foreach (PropertyInfo propertyInfo in properties)
{
if (propertyInfo.CanRead && propertyInfo.GetIndexParameters().Length == 0)
{
Console.WriteLine(offset + propertyInfo.Name + " : ");
}
}
if (fields)
{
FieldInfo[] fields2 = o.GetType().GetFields();
foreach (FieldInfo fieldInfo in fields2)
{
Console.WriteLine(offset + fieldInfo.Name + " : ");
}
}
}
else
{
Console.Write(offset);
Console.WriteLine(o);
}
}
public static int DoubleAsIntOrUIntToInt(double value)
{
if (!(value > 2147483647.0))
{
return (int)value;
}
return BitConverter.ToInt32(BitConverter.GetBytes((uint)value), 0);
}
public static int MaskCount(int mask)
{
return MaskCount(mask, 32);
}
public static int MaskCount(int mask, int max)
{
int num = 0;
int num2 = 0;
while (num2 < max)
{
if ((mask & 1) == 1)
{
num++;
}
num2++;
mask >>= 1;
}
return num;
}
public static Type GetTypeObjectFromPrimitiveType(PrimitiveType primType)
{
return primType switch
{
PrimitiveType.Double => typeof(double),
PrimitiveType.Integer => typeof(int),
PrimitiveType.Long => typeof(long),
PrimitiveType.Single => typeof(short),
PrimitiveType.String => typeof(string),
_ => throw new ArgumentException(string.Format(Resources.UnknownValueOfEnumeration, typeof(PrimitiveType).Name, primType)),
};
}
internal static object ConvertStringToPrimitive(string input, PrimitiveType primType, CultureInfo culture)
{
return primType switch
{
PrimitiveType.Double => double.Parse(input, culture.NumberFormat),
PrimitiveType.Integer => int.Parse(input, culture.NumberFormat),
PrimitiveType.Long => long.Parse(input, culture.NumberFormat),
PrimitiveType.Single => float.Parse(input, culture.NumberFormat),
PrimitiveType.String => input,
_ => throw new ArgumentException(string.Format(Resources.UnknownValueOfEnumeration, typeof(PrimitiveType).Name, primType)),
};
}
public static int Mask2Index(int mask)
{
return Mask2Index(mask, 32);
}
public static int Mask2Index(int mask, int max)
{
int num = 0;
int num2 = 1;
while (num < max)
{
if ((mask & num2) != 0)
{
return num;
}
num++;
num2 <<= 1;
}
return -1;
}
public static string ArrayToPrettyString(Array arr)
{
StringBuilder stringBuilder = new StringBuilder();
if (arr != null)
{
foreach (object item in arr)
{
if (item is Array)
{
stringBuilder.Append("{");
stringBuilder.Append(ArrayToPrettyString(item as Array));
stringBuilder.Append("},");
}
else
{
stringBuilder.Append(Convert.ToSingle(item));
stringBuilder.Append(",");
}
}
}
else
{
stringBuilder.Append("__NULL__");
}
return stringBuilder.ToString();
}
public static string ArrayToString(Array objects)
{
StringBuilder stringBuilder = new StringBuilder();
foreach (object @object in objects)
{
stringBuilder.Append(@object);
}
return stringBuilder.ToString();
}
public static Stream GetEmbeddedStream(string name)
{
return Assembly.GetExecutingAssembly().GetManifestResourceStream(name);
}
public static void DeleteFiles(string fileNameBase, string[] endings)
{
foreach (string text in endings)
{
DeleteFile(fileNameBase + text);
}
}
public static void DeleteFile(string fileName)
{
if (File.Exists(fileName))
{
File.SetAttributes(fileName, File.GetAttributes(fileName) & ~FileAttributes.ReadOnly);
File.Delete(fileName);
}
}
public static XmlElement FindNextElement(XmlNode xnCurr)
{
while (xnCurr != null && !(xnCurr is XmlElement))
{
xnCurr = xnCurr.NextSibling;
}
return xnCurr as XmlElement;
}
public static XmlAttribute CreateAttributeWithValue(XmlDocument xmlDoc, string qualifiedName, string value)
{
XmlAttribute xmlAttribute = xmlDoc.CreateAttribute(qualifiedName);
xmlAttribute.Value = value;
return xmlAttribute;
}
public static T EnumTo(Enum value)
{
return (T)Convert.ChangeType(Convert.ChangeType(value, Enum.GetUnderlyingType(value.GetType())), typeof(T));
}
public static string AlwaysEnUsToString(object obj)
{
CultureInfo cultureInfo = new CultureInfo("en-US", useUserOverride: false);
if (obj is double num)
{
return num.ToString("r", cultureInfo);
}
if (obj is float num2)
{
return num2.ToString("r", cultureInfo);
}
return obj.ToString();
}
public static IntPtr IncrementPointer(IntPtr baseAddress, Type offsetType)
{
if ((object)offsetType == null)
{
throw new ArgumentNullException("offsetType");
}
return IncrementPointer(baseAddress, Marshal.SizeOf(offsetType));
}
public static IntPtr IncrementPointer(IntPtr baseAddress, long offset)
{
return new IntPtr(baseAddress.ToInt64() + offset);
}
public static Thread ControllerResetWaiter(string resettingName, string resetName, ThreadStart resettingCode, ThreadStart resetCode, int millisecondsTimeout, KeepRunningContainer keepRunning)
{
EventWaitHandle resettingHandle = EventWaitHandle.OpenExisting(resettingName);
EventWaitHandle resetHandle = EventWaitHandle.OpenExisting(resetName);
Thread thread = new Thread(WrapDelegateForCulture(delegate
{
try
{
while (keepRunning.KeepRunning)
{
while (keepRunning.KeepRunning && !resettingHandle.WaitOne(millisecondsTimeout))
{
}
if (!keepRunning.KeepRunning)
{
break;
}
try
{
if (resettingCode != null)
{
resettingCode();
}
while (keepRunning.KeepRunning && !resetHandle.WaitOne(millisecondsTimeout))
{
}
}
finally
{
if (resetCode != null)
{
resetCode();
}
}
}
}
finally
{
resettingHandle.Close();
resetHandle.Close();
}
}));
thread.Name = $"Reset/Resetting ({resettingName}, {resetName})";
thread.IsBackground = true;
thread.Start();
return thread;
}
public static ThreadStart WrapDelegateForCulture(ThreadStart startDelegate)
{
if (startDelegate == null)
{
throw new ArgumentNullException("startDelegate");
}
CultureInfo callingThreadUICulture = Thread.CurrentThread.CurrentUICulture;
return delegate
{
CultureInfo currentUICulture = Thread.CurrentThread.CurrentUICulture;
try
{
Thread.CurrentThread.CurrentUICulture = callingThreadUICulture;
startDelegate();
}
finally
{
Thread.CurrentThread.CurrentUICulture = currentUICulture;
}
};
}
public static TaskId? ValidateTaskId(TaskId? taskId)
{
if (!taskId.HasValue)
{
throw new ArgumentNullException("taskId");
}
if (Enum.IsDefined(typeof(TaskId), taskId))
{
return taskId;
}
return null;
}
internal static ProgramFilePoint CreateProgramFilePoint(string sourceFilePath, string programFileName, int lineNumber)
{
string path;
PathKind programPathKind;
if (!string.IsNullOrEmpty(sourceFilePath) && File.Exists(sourceFilePath))
{
path = sourceFilePath;
programPathKind = PathKind.Source;
}
else
{
if (string.IsNullOrEmpty(programFileName))
{
return null;
}
path = programFileName;
programPathKind = PathKind.Object;
}
return new ProgramFilePoint(path, lineNumber, programPathKind);
}
public static TOut TryCultures(CultureTry work, CultureInfo ci) where TOut : class
{
CultureInfo cultureInfo = new CultureInfo("en-US", useUserOverride: false);
List list = new List();
list.Add(ci);
if (ci.TwoLetterISOLanguageName != ci.Name)
{
list.Add(ci.Parent);
}
if (ci.LCID != cultureInfo.LCID)
{
list.Add(cultureInfo);
}
return TryCultures(work, list);
}
public static TOut TryCultures(CultureTry work, IEnumerable cis) where TOut : class
{
TOut result = null;
foreach (CultureInfo ci in cis)
{
if ((result = work(ci)) != null)
{
return result;
}
}
return result;
}
}
以下是针对 InternalUtilities
类的详细中文分析,按功能分类整理:
这是一个 内部工具类,提供跨模块的通用辅助方法,主要涵盖:
类型转换(枚举、字符串、指针等)
数组/集合操作
线程与异步控制
调试输出
文件/XML处理
多文化(Culture)适配
方法签名 | 功能说明 | 示例 |
---|---|---|
SubArray |
截取子数组 | SubArray(arr, 2, 5) → 获取索引2-5的子数组 |
FillArray |
填充数组相同值 | FillArray(arr, 0) → 所有元素置0 |
Flip |
反转数组顺序 | Flip([1,2,3]) → [3,2,1] |
EnsureCapacity |
确保列表容量 | 自动扩容避免越界 |
方法 | 说明 | 典型场景 |
---|---|---|
EnumTo |
枚举值转任意类型 | EnumTo |
ConvertStringToPrimitive |
字符串转基础类型 | 支持double/int/long/float/string |
DoubleAsIntOrUIntToInt |
处理double到int的溢出 | 超过int.MaxValue 时按uint处理 |
GetTypeObjectFromPrimitiveType |
基础类型枚举转Type | PrimitiveType.Double → typeof(double) |
方法 | 功能 | 实现逻辑 |
---|---|---|
MaskCount |
计算掩码中1的位数 | 右移逐位检查 |
Mask2Index |
获取最低有效位索引 | 0b10010 → 返回1 |
方法 | 作用 | 关键点 |
---|---|---|
ControllerResetWaiter |
异步等待控制器重置 | 使用EventWaitHandle 同步信号 |
WrapDelegateForCulture |
保持委托的文化上下文 | 确保异步代码文化一致性 |
KeepRunningContainer |
线程安全停止标志 | 通过共享bool控制线程退出 |
方法 | 功能 | 备注 |
---|---|---|
OutputMyInfo |
反射输出对象详情 | 仅Debug模式生效,支持嵌套集合 |
ArrayToPrettyString |
格式化数组为字符串 | 递归处理多维数组 |
方法 | 描述 | 示例 |
---|---|---|
DeleteFiles |
批量删除带后缀文件 | DeleteFiles("log", [".txt", ".bak"]) |
FindNextElement |
查找下一个XML元素节点 | 跳过非元素节点 |
CreateAttributeWithValue |
快速创建XML属性 | 简化DOM操作 |
方法 | 功能 | 注意 |
---|---|---|
IncrementPointer |
指针地址偏移 | 支持按类型大小自动计算偏移量 |
方法 | 作用 | 策略 |
---|---|---|
TryCultures |
多文化回退尝试 | 依次尝试用户文化→父文化→en-US |
AlwaysEnUsToString |
强制en-US格式输出 | 浮点数使用"r"格式保证精度 |
var keeper = new KeepRunningContainer { KeepRunning = true };
var thread = InternalUtilities.ControllerResetWaiter(
"ResetEvent", "ResettingEvent",
() => Console.WriteLine("Resetting..."),
null, 1000, keeper
);
// 需要停止时
keeper.KeepRunning = false;
thread.Join();
// 字符串转数值(自动适配用户区域设置)
var value = InternalUtilities.ConvertStringToPrimitive(
"123.45",
PrimitiveType.Double,
CultureInfo.CurrentCulture
);
// 输出对象所有属性和字段(Debug模式)
InternalUtilities.OutputMyInfo(myObject, showFields: true);
文化意识
WrapDelegateForCulture
确保异步代码不因线程池文化设置丢失上下文。
TryCultures
实现多文化回退机制,增强国际化兼容性。
线程安全
KeepRunningContainer
提供统一的线程停止控制。
ControllerResetWaiter
封装复杂的事件等待逻辑。
防御性编程
关键方法(如EnumTo
)包含类型安全检查。
指针操作验证参数有效性。
异常处理增强
当前静默忽略部分异常(如bgWorker
中的catch空块),建议记录日志。
性能优化
ArrayToPrettyString
频繁拼接字符串,可改用StringBuilder
预分配容量。
扩展性
增加Span
支持以提升数组操作性能。
文档补充
添加XML注释说明各方法的线程安全性要求。
InternalUtilities
是一个功能密集的内部工具库,其设计体现了:
高复用性:跨模块共享基础功能。
可靠性:关键操作包含边界检查和异常处理。
国际化支持:深度集成文化适配逻辑。
适用于需要处理多文化、异步操作和复杂类型转换的系统级开发场景。