c# 生成对象的初始化代码

使用方法,
string code = InitializerCodeGenerator.GenerateInitializer(this);
例如:

  public class ParaParseConfig
  {
      public string ParaNo { get; set; }
      public JsonDataType ParaType { get; set; }

      public List<ParaParseConfig> Sub { get; set; }

      public string GetCode()
      {
          string code = InitializerCodeGenerator.GenerateInitializer(this);

          return code;
      }
  }

完整代码



    public static class InitializerCodeGenerator
    {
        public static string GenerateInitializer(object obj)
        {
            if (obj == null) return "null";
            var sb = new StringBuilder();
            BuildExpression(obj, sb, 0, new HashSet<object>(ReferenceEqualityComparer.Instance));
            return sb.ToString().TrimEnd('\r', '\n');
        }

        private static void BuildExpression(object obj, StringBuilder sb, int indent, HashSet<object> visited)
        {
            if (obj == null)
            {
                sb.Append("null");
                return;
            }

            if (visited.Contains(obj))
            {
                sb.Append("/* circular reference */");
                return;
            }

            Type type = obj.GetType();

            // 基本类型 / 字符串 / 枚举 / 可空类型 → 直接输出字面量
            if (IsSimpleType(type))
            {
                sb.Append(GetLiteral(obj));
                return;
            }

            // 可空类型(已经包含在 IsSimpleType 中,但单独处理也可)
            Type underlying = Nullable.GetUnderlyingType(type);
            if (underlying != null)
            {
                sb.Append(GetLiteral(obj));
                return;
            }

            visited.Add(obj);

            // 数组
            if (type.IsArray)
            {
                var arr = (Array)obj;
                Type elemType = type.GetElementType();
                sb.Append($"new {GetTypeName(elemType)}[{arr.Length}]{{");
                for (int i = 0; i < arr.Length; i++)
                {
                    if (i > 0) sb.Append(", ");
                    BuildExpression(arr.GetValue(i), sb, indent + 1, visited);
                }
                sb.Append("}");
                return;
            }

            // 泛型集合
            if (typeof(IEnumerable).IsAssignableFrom(type) && type.IsGenericType)
            {
                var enumerable = (IEnumerable)obj;
                var genericArgs = type.GetGenericArguments();

                // 字典
                if (type.GetInterfaces().Any(i => i.IsGenericType && i.GetGenericTypeDefinition() == typeof(IDictionary<,>)))
                {
                    var dict = (IDictionary)obj;
                    sb.Append($"new {GetTypeName(type)}(){{");
                    bool first = true;
                    foreach (DictionaryEntry entry in dict)
                    {
                        if (!first) sb.Append(", ");
                        first = false;
                        sb.Append("{ ");
                        BuildExpression(entry.Key, sb, indent + 1, visited);
                        sb.Append(", ");
                        BuildExpression(entry.Value, sb, indent + 1, visited);
                        sb.Append(" }");
                    }
                    sb.Append("}");
                }
                else // List, HashSet, Queue, Stack ...
                {
                    sb.Append($"new {GetTypeName(type)}(){{");
                    bool first = true;
                    foreach (var item in enumerable)
                    {
                        if (!first) sb.Append(", ");
                        first = false;
                        BuildExpression(item, sb, indent + 1, visited);
                    }
                    sb.Append("}");
                }
                return;
            }

            // 普通类 / 结构体 → 对象初始化器
            sb.AppendLine($"new {GetTypeName(type)}()");
            sb.AppendLine(new string(' ', indent * 4) + "{");

            // 公共可写属性(不含索引器)
            foreach (var prop in type.GetProperties(BindingFlags.Public | BindingFlags.Instance)
                                     .Where(p => p.CanWrite && p.GetIndexParameters().Length == 0))
            {
                object value = prop.GetValue(obj);
                if (value == null) continue;
                sb.Append(new string(' ', (indent + 1) * 4));
                sb.Append($"{prop.Name} = ");
                BuildExpression(value, sb, indent + 1, visited);
                sb.AppendLine(",");
            }

            // 公共字段
            foreach (var field in type.GetFields(BindingFlags.Public | BindingFlags.Instance))
            {
                object value = field.GetValue(obj);
                if (value == null) continue;
                sb.Append(new string(' ', (indent + 1) * 4));
                sb.Append($"{field.Name} = ");
                BuildExpression(value, sb, indent + 1, visited);
                sb.AppendLine(",");
            }

            sb.Append(new string(' ', indent * 4) + "}");
        }

        private static bool IsSimpleType(Type t)
        {
            if (t.IsPrimitive || t == typeof(string) || t.IsEnum || t == typeof(decimal) ||
                t == typeof(DateTime) || t == typeof(Guid) || t == typeof(TimeSpan) ||
                t == typeof(Uri) || t == typeof(Version))
                return true;
            Type underlying = Nullable.GetUnderlyingType(t);
            return underlying != null && IsSimpleType(underlying);
        }

        private static string GetLiteral(object value)
        {
            if (value == null) return "null";
            Type t = value.GetType();
            if (t == typeof(string)) return $"\"{EscapeString((string)value)}\"";
            if (t == typeof(char)) return $"'{value}'";
            if (t == typeof(bool)) return (bool)value ? "true" : "false";
            if (t.IsEnum) return $"{t.FullName}.{value}";
            if (t == typeof(decimal)) return $"{value}m";
            if (t == typeof(float)) return $"{value}f";
            if (t == typeof(double)) return $"{value}d";
            if (t == typeof(long)) return $"{value}L";
            if (t == typeof(uint)) return $"{value}u";
            if (t == typeof(ulong)) return $"{value}UL";
            if (t == typeof(DateTime)) return $"new DateTime({((DateTime)value).Ticks}L)";
            if (t == typeof(Guid)) return $"new Guid(\"{value}\")";
            if (t == typeof(TimeSpan)) return $"new TimeSpan({((TimeSpan)value).Ticks}L)";
            if (t == typeof(Uri)) return $"new Uri(\"{value}\")";
            if (t == typeof(Version)) return $"new Version(\"{value}\")";
            if (Nullable.GetUnderlyingType(t) != null)
            {
                var nullable = value as dynamic;
                return nullable.HasValue ? GetLiteral(nullable.Value) : "null";
            }
            return value.ToString(); // fallback
        }

        private static string EscapeString(string s)
        {
            return s.Replace("\\", "\\\\")
                    .Replace("\"", "\\\"")
                    .Replace("\n", "\\n")
                    .Replace("\r", "\\r")
                    .Replace("\t", "\\t");
        }

        private static string GetTypeName(Type type)
        {
            if (!type.IsGenericType) return type.FullName ?? type.Name;
            var sb = new StringBuilder();
            sb.Append(type.GetGenericTypeDefinition().FullName?.Split('`')[0]);
            sb.Append("<");
            var args = type.GetGenericArguments();
            for (int i = 0; i < args.Length; i++)
            {
                if (i > 0) sb.Append(", ");
                sb.Append(GetTypeName(args[i]));
            }
            sb.Append(">");
            return sb.ToString();
        }
    }

posted @ 2026-07-20 14:30  Hey,Coder!  阅读(1)  评论(0)    收藏  举报