// ========================= public DumpScript AddDumpedDictionary( DumpAttribute dumpAttribute) { if (dumpAttribute == null) { throw new ArgumentNullException(nameof(dumpAttribute)); } return(Add(DumpedDictionary(Expression.Convert(_instance, typeof(IDictionary)), dumpAttribute))); }
// =================================== public DumpScript AddDumpedCollection( DumpAttribute dumpAttribute) { if (dumpAttribute == null) { throw new ArgumentNullException(nameof(dumpAttribute)); } return(Add(DumpedCollection(dumpAttribute))); }
public static string DumpString( this object value, int indentLevel = 0, Type dumpMetadata = null, DumpAttribute dumpAttribute = null) { using (var writer = new StringWriter(CultureInfo.InvariantCulture)) { value.DumpText(writer, indentLevel, dumpMetadata, dumpAttribute); return(writer.GetStringBuilder().ToString()); } }
bool DumpedSequence( IEnumerable sequence, MemberInfo mi, DumpAttribute dumpAttribute, bool enumerateCustom = false, bool newLineForCustom = false) { if (sequence == null) { throw new ArgumentNullException(nameof(sequence)); } if (dumpAttribute == null) { throw new ArgumentNullException(nameof(dumpAttribute)); } var sequenceType = sequence.GetType(); var isCustom = !sequenceType.IsArray && !sequenceType.IsFromSystem(); var dumpCustom = enumerateCustom && dumpAttribute.Enumerate == ShouldDump.Dump; if (isCustom && !dumpCustom) { return(false); } if (IsInDumpingMode) { if (isCustom && newLineForCustom) { _dumper.Writer.WriteLine(); } return(_dumper.Writer.DumpedCollection( sequence, dumpAttribute, o => _dumper.DumpObject(o, null, null, this), _dumper.Indent, _dumper.Unindent)); } else { if (mi != null) { DumpScript.AddDumpedCollection(mi, dumpAttribute); } else { DumpScript.AddDumpedCollection(dumpAttribute); } return(true); } }
/// <summary> /// Advances the enumerator to the next element of the collection. /// </summary> /// <returns> /// true if the enumerator was successfully advanced to the next element; false if the enumerator has passed the end of the collection. /// </returns> public bool MoveNext() { if (!Enumerator.MoveNext()) { _currentMemberInfo = null; _currentDumpAttribute = null; return(false); } _currentMemberInfo = Enumerator.Current; _currentDumpAttribute = PropertyDumpResolver.GetPropertyDumpAttribute(_currentMemberInfo, ClassDumpData.Metadata); return(true); }
Expression DumpedDictionary( DumpAttribute dumpAttribute) { if (dumpAttribute == null) { throw new ArgumentNullException(nameof(dumpAttribute)); } return(DumpedDictionary( //// _instance _instance, dumpAttribute)); }
// ================================ dump the value of a property Expression DumpPropertyOrCollectionValue( MemberInfo mi, DumpAttribute dumpAttribute) { if (mi == null) { throw new ArgumentNullException(nameof(mi)); } if (dumpAttribute == null) { throw new ArgumentNullException(nameof(dumpAttribute)); } var pi = mi as PropertyInfo; var fi = pi != null ? null : mi as FieldInfo; var type = pi?.PropertyType ?? fi.FieldType; if (type.IsBasicType()) { return(DumpedBasicValue(mi)); } if (type.IsGenericType && type.GetGenericTypeDefinition() == typeof(Nullable <>) && type.GetGenericArguments()[0].IsBasicType()) { return(DumpedBasicNullable(mi)); } if (typeof(Delegate).IsAssignableFrom(type)) { return(DumpedDelegate(mi)); } if (typeof(MemberInfo).IsAssignableFrom(type)) { return(DumpedMemberInfo(mi)); } if (typeof(IEnumerable).IsAssignableFrom(type) && (type.IsArray || type.IsFromSystem())) { if (type.DictionaryTypeArguments() != null) { return(DumpedDictionary(mi, dumpAttribute)); } return(DumpedCollection(mi, dumpAttribute)); } return(DumpObject(mi, null, !dumpAttribute.IsDefaultAttribute() ? (Expression)_tempDumpAttribute : Expression.Convert(_null, typeof(DumpAttribute)))); }
public DumpScript AddDumpedCollection( MemberInfo mi, DumpAttribute dumpAttribute) { if (mi == null) { throw new ArgumentNullException(nameof(mi)); } if (dumpAttribute == null) { throw new ArgumentNullException(nameof(dumpAttribute)); } return(Add(DumpedCollection(mi, dumpAttribute))); }
bool DumpedCollection( object value, MemberInfo mi, DumpAttribute dumpAttribute, bool enumerateCustom = false, bool newLineForCustom = false) { if (!(value is IEnumerable sequence)) { return(false); } return(DumpedDictionary(sequence, mi, dumpAttribute) || DumpedSequence(sequence, mi, dumpAttribute, enumerateCustom, newLineForCustom)); }
bool DumpedDictionary( IEnumerable sequence, MemberInfo mi, DumpAttribute dumpAttribute) { if (sequence == null) { throw new ArgumentNullException(nameof(sequence)); } if (dumpAttribute == null) { throw new ArgumentNullException(nameof(dumpAttribute)); } if (sequence.IsDynamicObject()) { return(false); } if (IsInDumpingMode) { return(_dumper.Writer.DumpedDictionary( sequence, dumpAttribute, o => _dumper.DumpObject(o, null, null, this), _dumper.Indent, _dumper.Unindent)); } else { if (sequence.GetType().DictionaryTypeArguments() == null) { return(false); } if (mi != null) { DumpScript.AddDumpedDictionary(mi, dumpAttribute); } else { DumpScript.AddDumpedDictionary(dumpAttribute); } } return(true); }
public DumpScript BeginDumpProperty( MemberInfo mi, DumpAttribute dumpAttribute) { if (mi == null) { throw new ArgumentNullException(nameof(mi)); } Add(Expression.Assign(_tempDumpAttribute, Expression.Constant(dumpAttribute))); BeginScriptSegment(); AddWriteLine(); AddWrite( Expression.Constant(dumpAttribute.LabelFormat), Expression.Constant(mi.Name)); return(this); }
Expression DumpedDictionary( MemberInfo mi, DumpAttribute dumpAttribute) { if (mi == null) { throw new ArgumentNullException(nameof(mi)); } if (dumpAttribute == null) { throw new ArgumentNullException(nameof(dumpAttribute)); } return(DumpedDictionary( //// _instance.Property MemberValue(mi), dumpAttribute)); }
private DumpState( ObjectTextDumper dumper, object instance, Type type, ClassDumpData classDumpData, DumpAttribute instanceDumpAttribute, DumpScript dumpScript, bool isTopLevelClass) { _dumper = dumper ?? throw new ArgumentNullException(nameof(dumper)); _isTopLevelClass = isTopLevelClass; Instance = instance ?? throw new ArgumentNullException(nameof(instance)); InstanceType = instance.GetType(); CurrentType = type ?? throw new ArgumentNullException(nameof(type)); ClassDumpData = classDumpData; InstanceDumpAttribute = instanceDumpAttribute ?? throw new ArgumentNullException(nameof(instanceDumpAttribute)); DumpScript = dumpScript; if (_isTopLevelClass) { var defaultProperty = DefaultProperty; if (!defaultProperty.IsNullOrWhiteSpace()) { var pi = CurrentType.GetProperty(defaultProperty); Enumerator = pi != null ? (new MemberInfo[] { pi }).AsEnumerable().GetEnumerator() : (new MemberInfo[] { }).AsEnumerable().GetEnumerator(); return; } } Enumerator = CurrentType.GetProperties(_dumper.PropertiesBindingFlags | BindingFlags.DeclaredOnly) .Union <MemberInfo>( CurrentType.GetFields(_dumper.FieldsBindingFlags | BindingFlags.DeclaredOnly)) .Where(mi => !mi.Name.StartsWith("<", StringComparison.Ordinal)) .OrderBy(p => p, ServiceResolver .Default .GetInstance <IMemberInfoComparer>() .SetMetadata(ClassDumpData.Metadata)) .GetEnumerator(); }
Expression DumpedCollection( DumpAttribute dumpAttribute) { if (dumpAttribute == null) { throw new ArgumentNullException(nameof(dumpAttribute)); } var piCount = _instance.Type.IsArray ? _piArrayLength : _instance.Type.GetProperty(nameof(ICollection.Count), BindingFlags.Public | BindingFlags.Instance); var count = piCount != null ? Expression.Property(_instance, piCount) : null; return(DumpedCollection( //// _instance _instance, dumpAttribute, count)); }
Expression DumpedCollection( MemberInfo mi, DumpAttribute dumpAttribute) { if (mi == null) { throw new ArgumentNullException(nameof(mi)); } if (dumpAttribute == null) { throw new ArgumentNullException(nameof(dumpAttribute)); } Expression count = null; var type = (mi as PropertyInfo)?.PropertyType ?? (mi as FieldInfo)?.FieldType; if (type != null) { if (type.IsArray) { count = Expression.Property(MemberValue(mi), _piArrayLength); } else { var piCount = type.GetProperty(nameof(ICollection.Count), BindingFlags.Public | BindingFlags.Instance); if (piCount != null) { count = Expression.Property(MemberValue(mi), piCount); } } } return(DumpedCollection( //// _instance.Property MemberValue(mi), dumpAttribute, count)); }
// ========================== Add dumping of a property public DumpScript AddDumpPropertyOrCollectionValue( MemberInfo mi, DumpAttribute dumpAttribute) { if (mi == null) { throw new ArgumentNullException(nameof(mi)); } if (dumpAttribute == null) { throw new ArgumentNullException(nameof(dumpAttribute)); } var ex = DumpPropertyOrCollectionValue(mi, dumpAttribute); if (ex != null) { return(Add(ex)); } return(this); }
internal static int GetMaxToDump( this DumpAttribute dumpAttribute, int length = int.MaxValue) { if (dumpAttribute == null) { throw new ArgumentNullException(nameof(dumpAttribute)); } var max = dumpAttribute.MaxLength; if (max < 0) { return(length); } if (max == 0) // limit sequences of primitive types (can be very big) { return(Math.Min(DumpAttribute.DefaultMaxElements, length)); } return(Math.Min(max, length)); }
public static object DumpText( this object value, TextWriter writer, int indentLevel = 0, Type dumpMetadata = null, DumpAttribute dumpAttribute = null) { if (writer == null) { throw new ArgumentNullException(nameof(writer)); } try { using (var dumper = new ObjectTextDumper(writer)) dumper.Dump(value, dumpMetadata, dumpAttribute, indentLevel); } catch (Exception x) { writer.WriteLine($"\n\nATTENTION:\nThe TextDumper threw an exception:\n{x.ToString()}"); } return(value); }
public bool DumpedCollection( DumpAttribute dumpAttribute, bool enumerateCustom) => DumpedCollection(Instance, null, dumpAttribute, enumerateCustom, true);
/// <summary> /// Sets the enumerator to its initial position, which is before the first element in the collection. /// </summary> public void Reset() { Enumerator.Reset(); _currentMemberInfo = null; _currentDumpAttribute = null; }
Expression DumpedDictionary( Expression dictionary, DumpAttribute dumpAttribute) { if (dictionary == null) { throw new ArgumentNullException(nameof(dictionary)); } if (dumpAttribute == null) { throw new ArgumentNullException(nameof(dumpAttribute)); } //// dictionary.GetType() var dictionaryType = Expression.Call(dictionary, _miGetType); BeginScriptSegment(); //// writer.Write(DumpFormat.SequenceTypeName, dictionaryType.GetTypeName(), dictionary.Count.ToString(CultureInfo.InvariantCulture)); //// writer.Write(DumpFormat.SequenceType, dictionaryType.GetTypeName(), dictionaryType.Namespace, dictionaryType.AssemblyQualifiedName); AddDumpSequenceTypeName(dictionary, dictionaryType); AddDumpSequenceType(dictionaryType); if (dumpAttribute.RecurseDump == ShouldDump.Skip) { //// return true; _script.Add(Expression.Constant(true)); return(Expression.Block(EndScriptSegment())); } ParameterExpression kv; // the current key-value item ParameterExpression n; // how many items left to be dumped? ParameterExpression max; // max items to dump ParameterExpression count; // count of items kv = Expression.Parameter(typeof(DictionaryEntry), nameof(kv)); n = Expression.Parameter(typeof(int), nameof(n)); max = Expression.Parameter(typeof(int), nameof(max)); count = Expression.Parameter(typeof(int), nameof(count)); var @break = Expression.Label(); _script.Add ( //// if (ReferenceEqual(dictionary,null)) return false; else { Expression.IfThenElse ( Expression.Call(_miReferenceEquals, dictionary, _null), Expression.Block ( Expression.Assign(_tempBool, _false), Write(_stringNull) ), Expression.Block ( //// var kv; var n=0; var max = dumpAttribute.GetMaxToDump(sequence.Count); n = 0; WriteLine(); Write("{"); Indent(); new[] { kv, n, max, count }, Expression.Assign(n, _zero), Expression.Assign(count, Expression.Property(dictionary, _piCollectionCount)), Expression.Assign(max, Expression.Call(_miGetMaxToDump, Expression.Constant(dumpAttribute, typeof(DumpAttribute)), count)), WriteLine(), Write(Resources.DictionaryBegin), Indent(), //// foreach (kv in dictionary) ForEachInDictionary ( kv, dictionary, Expression.Block ( //// { Writer.WriteLine(); WriteLine(), //// if (n++ >= max) { Expression.IfThen ( Expression.GreaterThanOrEqual(Expression.PostDecrementAssign(n), max), Expression.Block ( //// Writer.Write(DumpFormat.SequenceDumpTruncated, max); Write(DumpFormat.SequenceDumpTruncated, Expression.Convert(max, typeof(object)), Expression.Convert(count, typeof(object))), //// break; } Expression.Break(@break) ) ), //// Writer.Write("["); Write(Resources.DictionaryKeyBegin), //// _dumper.DumpObject(kv.Key); Expression.Call(_dumper, _miDumperDumpObject, Expression.Property(kv, _piDictionaryEntryKey), Expression.Convert(_null, typeof(Type)), Expression.Convert(_null, typeof(DumpAttribute)), _dumpState), // Writer.Write("] = "); Write(Resources.DictionaryKeyEnd), //// _dumper.DumpObject(kv.Value); Expression.Call(_dumper, _miDumperDumpObject, Expression.Property(kv, _piDictionaryEntryValue), Expression.Convert(_null, typeof(Type)), Expression.Convert(_null, typeof(DumpAttribute)), _dumpState) // } ), @break ), Unindent(), WriteLine(), Write(Resources.DictionaryEnd), //// return true; } Expression.Assign(_tempBool, Expression.Constant(true)) ) ) ); return(Expression.Block(EndScriptSegment())); }
// ============================== Expression DumpedCollection( Expression sequence, DumpAttribute dumpAttribute, Expression expressionCount = null) { if (sequence == null) { throw new ArgumentNullException(nameof(sequence)); } if (dumpAttribute == null) { throw new ArgumentNullException(nameof(dumpAttribute)); } ParameterExpression n; // how many items left to be dumped? ParameterExpression max; // max items to dump ParameterExpression item; // the iteration variable ParameterExpression bytes; // collection as byte[]; ParameterExpression isArray; // flag that the sequence is an array of items ParameterExpression sequenceType; // the type of the sequence n = Expression.Parameter(typeof(int), nameof(n)); max = Expression.Parameter(typeof(int), nameof(max)); item = Expression.Parameter(typeof(object), nameof(item)); bytes = Expression.Parameter(typeof(byte[]), nameof(bytes)); isArray = Expression.Parameter(typeof(bool), nameof(isArray)); sequenceType = Expression.Parameter(typeof(Type), nameof(sequenceType)); var @break = Expression.Label(); ////var elementsType = sequenceType.IsArray //// ? new Type[] { sequenceType.GetElementType() } //// : sequenceType.IsGenericType //// ? sequenceType.GetGenericArguments() //// : new Type[] { typeof(object) }; var elementsType = Expression.Condition( Expression.Property(sequenceType, _piIsArray), Expression.NewArrayInit(typeof(Type), Expression.Call(sequenceType, _miGetElementType)), Expression.Condition( Expression.Property(sequenceType, _piIsGenericType), Expression.Call(sequenceType, _miGetGenericArguments), Expression.NewArrayInit(typeof(Type), Expression.Constant(typeof(object))))); var truncatedCount = expressionCount != null ? (Expression)Expression.Convert(expressionCount, typeof(object)) : Expression.Constant(Resources.StringUnknown); BeginScriptSegment(); Add ( ////writer.Write( //// DumpFormat.SequenceType, //// sequenceType.GetTypeName(), //// sequenceType.Namespace, //// sequenceType.AssemblyQualifiedName); Write ( DumpFormat.SequenceType, Expression.Call(_miGetTypeName, sequenceType, _false), Expression.Property(sequenceType, _piNamespace), Expression.Property(sequenceType, _piAssemblyQualifiedName) ) ); if (dumpAttribute.RecurseDump != ShouldDump.Skip) { Add ( ////indent(); ////foreach (var item in sequence) ////{ //// writer.WriteLine(); //// if (n++ >= max) //// { //// writer.Write(DumpFormat.SequenceDumpTruncated, max); //// break; //// } //// dumpObject(item); ////} ////unindent(); Expression.Block ( Indent(), ForEachInEnumerable ( item, sequence, Expression.Block ( WriteLine(), Expression.IfThen ( Expression.GreaterThanOrEqual(Expression.PostIncrementAssign(n), max), Expression.Block ( Write(DumpFormat.SequenceDumpTruncated, Expression.Convert(max, typeof(object)), truncatedCount), Expression.Break(@break) ) ), Expression.Call(_dumper, _miDumperDumpObject, item, Expression.Convert(_null, typeof(Type)), Expression.Convert(_null, typeof(DumpAttribute)), _dumpState) ), @break ), Unindent() ) ); } var dumpingLoop = EndScriptSegment(); //// if (ReferenceEqual(collection,null)) Writer.Write("<null>"); else { return(Expression.Block ( Expression.IfThenElse ( Expression.Call(_miReferenceEquals, sequence, _null), Expression.Block ( Expression.Assign(_tempBool, _false), Write(_stringNull) ), Expression.Block ( //// var max = dumpAttribute.GetMaxToDump(sequence.Count); var n = 0; var bytes = collection as byte[]; var count = collection.Count(); new[] { sequenceType, n, max, bytes, isArray }, //// sequence.GetType() Expression.Assign(sequenceType, Expression.Call(sequence, _miGetType)), Expression.Assign(n, _zero), Expression.Assign(isArray, Expression.Property(sequenceType, _piIsArray)), Expression.Assign(max, Expression.Call(_miGetMaxToDump, _tempDumpAttribute, expressionCount ?? _intMax)), Expression.Assign(bytes, Expression.TypeAs(sequence, typeof(byte[]))), //// if (!(sequenceType.IsArray || sequenceType.IsFromSystem())) WriteLine(); Expression.IfThen ( Expression.Not ( Expression.OrElse ( Expression.Property(sequenceType, _piIsArray), Expression.Call(_miIsMatch, sequenceType) ) ), WriteLine() ), ////writer.Write( //// DumpFormat.SequenceTypeName, //// sequenceType.IsArray //// ? elementsType[0].GetTypeName() //// : sequenceType.GetTypeName(), //// collection != null //// ? collection.Count.ToString(CultureInfo.InvariantCulture) //// : string.Empty); Write ( DumpFormat.SequenceTypeName, Expression.Condition ( isArray, Expression.Call(_miGetTypeName, Expression.ArrayIndex(elementsType, _zero), _false), Expression.Call(_miGetTypeName, sequenceType, _false) ), expressionCount != null ? (Expression)Expression.Condition ( Expression.NotEqual(sequence, _null), Expression.Call(expressionCount, _miIntToString1, Expression.Constant(CultureInfo.InvariantCulture)), _empty ) : _empty ), ////if (bytes != null) ////{ //// // dump no more than max elements from the sequence: //// writer.Write(BitConverter.ToString(bytes, 0, max)); //// if (max < bytes.Length) //// writer.Write(DumpFormat.SequenceDumpTruncated, max); ////} Expression.IfThenElse ( Expression.NotEqual(bytes, _null), Expression.Block ( Write(Expression.Call(_miBitConverterToString, bytes, _zero, max)), Expression.IfThen ( Expression.LessThan(max, Expression.Property(bytes, _piArrayLength)), Write(DumpFormat.SequenceDumpTruncated, Expression.Convert(max, typeof(object)), truncatedCount) ) ), ////else { Expression.Block ( dumpingLoop ) //// } ), //// return true; } Expression.Assign(_tempBool, Expression.Constant(true)) ) ) )); }