Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

In C#, how do you one-way serialize the unserializable?

Oftentimes, I need to serialize an object, either for logging or debugging. This is a one-way serialization -- I don't need to get it back out later, I just need to turn an object into a string to write it somewhere.

Yes, yes -- this is why you should always override the ToString method. I know this. But I'm often dealing with objects I didn't write and can't change. Additionally, I don't want to have to write and update a ToString method for every class I write.

XML serialization offers a seemingly perfect solution -- just flatten that object out into XML. But there are so many limitations, specifically that you can't serialize IDictionary, and you have to have a parameterless constructor. I can get around these in my classes, but -- again -- I'm often working with other people's classes.

So, what's the solution to getting an comprehensive string representation of an object? Is there something simple that I'm missing?

like image 856
Deane Avatar asked Dec 19 '12 15:12

Deane


People also ask

What does |= mean in C?

The ' |= ' symbol is the bitwise OR assignment operator.

What is '~' in C programming?

In mathematics, the tilde often represents approximation, especially when used in duplicate, and is sometimes called the "equivalency sign." In regular expressions, the tilde is used as an operator in pattern matching, and in C programming, it is used as a bitwise operator representing a unary negation (i.e., "bitwise ...

What is an operator in C?

C operators are one of the features in C which has symbols that can be used to perform mathematical, relational, bitwise, conditional, or logical manipulations. The C programming language has a lot of built-in operators to perform various tasks as per the need of the program.

What is the use of in C?

In C/C++, the # sign marks preprocessor directives. If you're not familiar with the preprocessor, it works as part of the compilation process, handling includes, macros, and more.


2 Answers

How about an extension method with your own logic (and maybe some Reflection)?

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;     } } 

Call it like so:

someDefinedObject.OneWaySerialize(); 

Revisisons

  1. Initial version
  2. Updated 12.26.2012
    • Added check for IEnumerable (thanks aboveyou00)
    • Added check for anonymous type (and just label it "new" when output)
like image 109
Brad Christie Avatar answered Sep 19 '22 22:09

Brad Christie


If you're comfortable serializing to JSON, Json.NET is a great solution to this problem.

like image 23
David Peden Avatar answered Sep 21 '22 22:09

David Peden