一个内部工具类InternalUtility的实现

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 类的详细中文分析,按功能分类整理:


1. 核心功能

这是一个 内部工具类,提供跨模块的通用辅助方法,主要涵盖:

  • 类型转换(枚举、字符串、指针等)

  • 数组/集合操作

  • 线程与异步控制

  • 调试输出

  • 文件/XML处理

  • 多文化(Culture)适配


2. 关键方法分类解析

(1)数组/集合操作
方法签名 功能说明 示例
SubArray 截取子数组 SubArray(arr, 2, 5) → 获取索引2-5的子数组
FillArray 填充数组相同值 FillArray(arr, 0) → 所有元素置0
Flip 反转数组顺序 Flip([1,2,3]) → [3,2,1]
EnsureCapacity 确保列表容量 自动扩容避免越界
(2)类型转换
方法 说明 典型场景
EnumTo 枚举值转任意类型 EnumTo(MyEnum.Value)
ConvertStringToPrimitive 字符串转基础类型 支持double/int/long/float/string
DoubleAsIntOrUIntToInt 处理double到int的溢出 超过int.MaxValue时按uint处理
GetTypeObjectFromPrimitiveType 基础类型枚举转Type PrimitiveType.Double → typeof(double)
(3)位掩码操作
方法 功能 实现逻辑
MaskCount 计算掩码中1的位数 右移逐位检查
Mask2Index 获取最低有效位索引 0b10010 → 返回1
(4)线程控制
方法 作用 关键点
ControllerResetWaiter 异步等待控制器重置 使用EventWaitHandle同步信号
WrapDelegateForCulture 保持委托的文化上下文 确保异步代码文化一致性
KeepRunningContainer 线程安全停止标志 通过共享bool控制线程退出
(5)调试工具
方法 功能 备注
OutputMyInfo 反射输出对象详情 仅Debug模式生效,支持嵌套集合
ArrayToPrettyString 格式化数组为字符串 递归处理多维数组
(6)文件/XML处理
方法 描述 示例
DeleteFiles 批量删除带后缀文件 DeleteFiles("log", [".txt", ".bak"])
FindNextElement 查找下一个XML元素节点 跳过非元素节点
CreateAttributeWithValue 快速创建XML属性 简化DOM操作
(7)指针操作
方法 功能 注意
IncrementPointer 指针地址偏移 支持按类型大小自动计算偏移量
(8)多文化(Culture)适配
方法 作用 策略
TryCultures 多文化回退尝试 依次尝试用户文化→父文化→en-US
AlwaysEnUsToString 强制en-US格式输出 浮点数使用"r"格式保证精度

3. 典型使用场景

场景1:异步线程安全停止
var keeper = new KeepRunningContainer { KeepRunning = true };
var thread = InternalUtilities.ControllerResetWaiter(
    "ResetEvent", "ResettingEvent", 
    () => Console.WriteLine("Resetting..."),
    null, 1000, keeper
);

// 需要停止时
keeper.KeepRunning = false;
thread.Join();
场景2:安全类型转换
// 字符串转数值(自动适配用户区域设置)
var value = InternalUtilities.ConvertStringToPrimitive(
    "123.45", 
    PrimitiveType.Double, 
    CultureInfo.CurrentCulture
);
场景3:调试对象结构
// 输出对象所有属性和字段(Debug模式)
InternalUtilities.OutputMyInfo(myObject, showFields: true);

4. 设计亮点

  1. 文化意识

    • WrapDelegateForCulture 确保异步代码不因线程池文化设置丢失上下文。

    • TryCultures 实现多文化回退机制,增强国际化兼容性。

  2. 线程安全

    • KeepRunningContainer 提供统一的线程停止控制。

    • ControllerResetWaiter 封装复杂的事件等待逻辑。

  3. 防御性编程

    • 关键方法(如EnumTo)包含类型安全检查。

    • 指针操作验证参数有效性。


5. 改进建议

  1. 异常处理增强

    • 当前静默忽略部分异常(如bgWorker中的catch空块),建议记录日志。

  2. 性能优化

    • ArrayToPrettyString频繁拼接字符串,可改用StringBuilder预分配容量。

  3. 扩展性

    • 增加Span支持以提升数组操作性能。

  4. 文档补充

    • 添加XML注释说明各方法的线程安全性要求。


总结

InternalUtilities 是一个功能密集的内部工具库,其设计体现了:

  • 高复用性:跨模块共享基础功能。

  • 可靠性:关键操作包含边界检查和异常处理。

  • 国际化支持:深度集成文化适配逻辑。

适用于需要处理多文化、异步操作和复杂类型转换的系统级开发场景。

你可能感兴趣的:(C#,c#)