/// <summary> /// Dynamically generates a formatter function that will output the public properties of objects of type <typeparamref name = "T" /> as a string. /// </summary> /// <typeparam name = "T">The <see cref = "Type" /> targeted by the formatter function.</typeparam> /// <returns>A formatter function.</returns> public Func <T, string> CreatePropertiesFormatter <T>(bool includeInternals = false) { var write = Formatter <T> .GenerateForAllMembers(includeInternals); return(t => { var writer = Formatter.CreateWriter(); write(t, writer); return writer.ToString(); }); }
private static void RegisterDefaults() { RegisterDefaultLogEntryFormatters(); // common primitive types Formatter <bool> .Default = (value, writer) => writer.Write(value); Formatter <byte> .Default = (value, writer) => writer.Write(value); Formatter <Int16> .Default = (value, writer) => writer.Write(value); Formatter <Int32> .Default = (value, writer) => writer.Write(value); Formatter <Int64> .Default = (value, writer) => writer.Write(value); Formatter <Guid> .Default = (value, writer) => writer.Write(value); Formatter <Decimal> .Default = (value, writer) => writer.Write(value); Formatter <Single> .Default = (value, writer) => writer.Write(value); Formatter <Double> .Default = (value, writer) => writer.Write(value); Formatter <DateTime> .Default = (value, writer) => writer.Write(value.ToString("u")); Formatter <DateTimeOffset> .Default = (value, writer) => writer.Write(value.ToString("u")); // common complex types Formatter <KeyValuePair <string, object> > .Default = (pair, writer) => { writer.Write(pair.Key); TextFormatter.WriteNameValueDelimiter(writer); pair.Value.FormatTo(writer); }; Formatter <DictionaryEntry> .Default = (pair, writer) => { writer.Write(pair.Key); TextFormatter.WriteNameValueDelimiter(writer); pair.Value.FormatTo(writer); }; Formatter <ExpandoObject> .Default = (expando, writer) => { TextFormatter.WriteStartObject(writer); KeyValuePair <string, object>[] pairs = expando.ToArray(); int length = pairs.Length; for (int i = 0; i < length; i++) { KeyValuePair <string, object> pair = pairs[i]; writer.Write(pair.Key); TextFormatter.WriteNameValueDelimiter(writer); pair.Value.FormatTo(writer); if (i < length - 1) { TextFormatter.WritePropertyDelimiter(writer); } } TextFormatter.WriteEndObject(writer); }; Formatter <Type> .Default = (type, writer) => { var typeName = type.Name; if (type.IsGenericType && !type.IsAnonymous()) { writer.Write(typeName.Remove(typeName.IndexOf('`'))); writer.Write("<"); var genericArguments = type.GetGenericArguments(); for (int i = 0; i < genericArguments.Length; i++) { Formatter <Type> .Default(genericArguments[i], writer); if (i < genericArguments.Length - 1) { writer.Write(","); } } writer.Write(">"); } else { writer.Write(typeName); } }; // an additional formatter is needed since typeof(Type) == System.RuntimeType, which is not public Register(typeof(Type).GetType(), (obj, writer) => Formatter <Type> .Default((Type)obj, writer)); // supply a formatter for String so that it will not be iterated Formatter <string> .Default = (s, writer) => writer.Write(s); // extensions Formatter <Counter> .Default = Formatter <Counter> .GenerateForAllMembers(); Formatter <Tracing> .Default = Formatter <Tracing> .GenerateForAllMembers(); // Newtonsoft.Json types -- these implement IEnumerable and their default output is not useful, so use their default ToString TryRegisterDefault("Newtonsoft.Json.Linq.JArray, Newtonsoft.Json", (obj, writer) => writer.Write(obj)); TryRegisterDefault("Newtonsoft.Json.Linq.JObject, Newtonsoft.Json", (obj, writer) => writer.Write(obj)); }