通常,我需要序列化一个对象,用于记录或调试。这是一种单向序列化——我不需要稍后将其取回,我只需要将一个对象变成一个字符串以将其写入某处。
是的,是的——这就是为什么您应该始终覆盖 ToString
方法的原因。我知道这个。但我经常处理我没有编写且无法更改的对象。此外,我不想为我编写的每个类编写和更新 ToString 方法。
XML 序列化提供了一个看似完美的解决方案——只需将该对象扁平化为 XML。但是有很多限制,特别是你不能序列化 IDictionary,你必须有一个无参数的构造函数。我可以在我的类里面解决这些问题,但是——同样——我经常和其他人的类一起工作。
那么,获得对象的综合字符串表示的解决方案是什么?有什么简单的东西是我遗漏的吗?
最佳答案
使用您自己的逻辑(也许还有一些反射)的扩展方法怎么样?
public static class SerializerExtension
{
public static String OneWaySerialize(this Object obj)
{
if (Object.ReferenceEquals(obj, null))
{
return "NULL";
}
if (obj.GetType().IsPrimitive || obj.GetType() == typeof(String))
{
if (obj is String)
return String.Format("\"{0}\"", obj);
if (obj is Char)
return String.Format("'{0}'", obj);
return obj.ToString();
}
StringBuilder builder = new StringBuilder();
Type objType = obj.GetType();
if (IsEnumerableType(objType))
{
builder.Append("[");
IEnumerator enumerator = ((IEnumerable)obj).GetEnumerator();
Boolean moreElements = enumerator.MoveNext();
while (moreElements)
{
builder.Append(enumerator.Current.OneWaySerialize());
moreElements = enumerator.MoveNext();
if (moreElements)
{
builder.Append(",");
}
}
builder.Append("]");
}
else
{
builder.AppendFormat("{0} {{ ", IsAnonymousType(objType) ? "new" : objType.Name);
PropertyInfo[] properties = objType.GetProperties();
for (Int32 p = properties.Length; p > 0; p--)
{
PropertyInfo prop = properties[p-1];
String propName = prop.Name;
Object propValue = prop.GetValue(obj, null);
builder.AppendFormat("{0} = {1}", propName, propValue.OneWaySerialize());
if (p > 1)
{
builder.Append(", ");
}
}
builder.Append(" }");
}
return builder.ToString();
}
// http://stackoverflow.com/a/2483054/298053
private static Boolean IsAnonymousType(Type type)
{
if (type == null)
{
return false;
}
return Attribute.IsDefined(type, typeof(System.Runtime.CompilerServices.CompilerGeneratedAttribute), false)
&& type.IsGenericType && type.Name.Contains("AnonymousType")
&& (type.Name.StartsWith("<>") || type.Name.StartsWith("VB$"))
&& (type.Attributes & TypeAttributes.NotPublic) == TypeAttributes.NotPublic;
}
private static Boolean IsEnumerableType(Type type)
{
if (type == null)
{
return false;
}
foreach (Type intType in type.GetInterfaces())
{
if (intType.GetInterface("IEnumerable") != null || (intType.IsGenericType && intType.GetGenericTypeDefinition() == typeof(IEnumerable<>)))
{
return true;
}
}
return false;
}
}
这样调用它:
someDefinedObject.OneWaySerialize();
修订
- 初始版本
- 更新于 2012 年 12 月 26 日
- 添加了对 IEnumerable 的检查(感谢 aboveyou00)
- 添加了对匿名类型的检查(并在输出时将其标记为"new")
关于c# - 在 C# 中,如何单向序列化不可序列化的对象?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/13955540/