/// <summary> /// Registers the dump metadata and <see cref="DumpAttribute" /> instance related to the specified type. /// </summary> /// <param name="type">The type for which the metadata is being registered.</param> /// <param name="metadataType">The dump metadata type.</param> /// <param name="dumpAttribute">The dump attribute.</param> /// <param name="replace"> /// If set to <see langword="false" /> and there is already dump metadata associated with the <paramref name="type"/> /// the method will throw exception of type <see cref="InvalidOperationException"/>; /// otherwise it will silently override the existing metadata with <paramref name="metadataType"/> and <paramref name="dumpAttribute"/>. /// </param> /// <returns>The current instance of ClassMetadataRegistrar.</returns> /// <exception cref="T:System.ArgumentNullException">Thrown if <paramref name="type" /> is <see langword="null" />.</exception> /// <exception cref="InvalidOperationException"> /// Thrown if <paramref name="replace"/> is <see langword="false"/> and there is already metadata associated with the <paramref name="type"/>. /// </exception> public ClassMetadataRegistrar Register( Type type, Type metadataType, DumpAttribute dumpAttribute = null, bool replace = false) { if (type == null) { throw new ArgumentNullException(nameof(type)); } ClassMetadataResolver.SetClassDumpData(type, metadataType, dumpAttribute, replace); return(this); }
/// <summary> /// Registers the metadata defined in <see cref="ExternalMetadata"/>. /// Allows for chaining further registering more dump metadata. /// </summary> /// <returns>ClassMetadataRegistrar.</returns> public static ClassMetadataRegistrar RegisterMetadata() { ClassMetadataResolver.SetClassDumpData(typeof(Task <>), typeof(TaskGenericDumpMetadata)); return(new ClassMetadataRegistrar() .Register <Type, TypeDumpMetadata>() .Register <Exception, ExceptionDumpMetadata>() .Register <ArgumentException, ArgumentExceptionDumpMetadata>() .Register <SecurityException, SecurityExceptionDumpMetadata>() .Register <CultureInfo, CultureInfoDumpMetadata>() .Register <Task, TaskDumpMetadata>() .Register <ClaimsIdentity, ClaimsIdentityMetadata>() .Register <Claim, ClaimMetadata>() .Register <Expression, ExpressionDumpMetadata>() .Register <LambdaExpression, LambdaExpressionDumpMetadata>() .Register <ParameterExpression, ParameterExpressionDumpMetadata>() .Register <BinaryExpression, BinaryExpressionDumpMetadata>() .Register <ConstantExpression, ConstantExpressionDumpMetadata>() ); // Do not extend the BCL dependency, but the client can call also: // //using System.Data; //using System.Data.Metadata.Edm; //using System.Data.SqlClient; //using System.Net; //using Microsoft.Practices.EnterpriseLibrary.Validation; //using Microsoft.Practices.EnterpriseLibrary.Validation.PolicyInjection; // //.Register<SqlException, SqlExceptionDumpMetadata>() //.Register<SqlError, SqlErrorDumpMetadata>() //.Register<ArgumentValidationException, ArgumentValidationExceptionDumpMetadata>() //.Register<MetadataItem, MetadataItemDumpMetadata>() //.Register<UpdateException, UpdateExceptionDumpMetadata>() //.Register<ValidationResult, ValidationResultDumpMetadata>() //.Register<ValidationResults, ValidationResultsDumpMetadata>() //.Register<ConfigurationErrorsException, ConfigurationErrorsExceptionDumpMetadata>() //.Register<WebException, WebExceptionDumpMetadata>() ; }
internal void DumpObject( object obj, Type dumpMetadata = null, DumpAttribute dumpAttribute = null, DumpState parentState = null) { if (Writer.DumpedBasicValue(obj, dumpAttribute) || Writer.DumpedBasicNullable(obj, dumpAttribute)) // incl. null { return; } // resolve the class metadata and the dump attribute ClassDumpData classDumpData; var objectType = obj.GetType(); if (dumpMetadata == null) { classDumpData = ClassMetadataResolver.GetClassDumpData(objectType); if (dumpAttribute != null) { classDumpData.DumpAttribute = dumpAttribute; } } else { classDumpData = new ClassDumpData(dumpMetadata, dumpAttribute); } // if we're too deep - stop here. if (_maxDepth == int.MinValue) { _maxDepth = classDumpData.DumpAttribute.MaxDepth; } if (_maxDepth < 0) { Writer.Write(Resources.DumpReachedMaxDepth); return; } // save here the IsSubExpression flag as it will change if obj is Expression and IsSubExpression==false. // but in the end of this method restore the value from this local variable. See below. var isSubExpressionStore = IsSubExpression; // slow dump vs. run script? bool isTopLevelObject = parentState == null; var buildScript = UseDumpScriptCache && !obj.IsDynamicObject(); Script script = null; using (var state = new DumpState(this, obj, classDumpData, buildScript)) { if (buildScript) { // does the script exist or is it in process of building if (DumpScriptCache.TryFind(this, obj, classDumpData, out script)) { if (script != null) { if (isTopLevelObject) { Writer.Indent(_indentLevel, _indentSize) .WriteLine(); } script(obj, classDumpData, this, state); } return; } DumpScriptCache.BuildingScriptFor(this, objectType, classDumpData); } else { if (isTopLevelObject) { Writer.Indent(_indentLevel, _indentSize) .WriteLine(); } } if (!state.DumpedAlready()) // the object has been dumped already (block circular and repeating references) { // this object will be dumped below. // Add it to the dumped objects now so that if nested property refers back to it, it won't be dumped in an infinite recursive chain. DumpedObjects.Add(new DumpedObject(obj, objectType)); if (!state.DumpedCollection(classDumpData.DumpAttribute, false)) // custom collections are dumped after dumping all other properties (see below * ) { Stack <DumpState> statesWithRemainingProperties = new Stack <DumpState>(); Queue <DumpState> statesWithTailProperties = new Queue <DumpState>(); // recursively dump all properties with non-negative order in class inheritance descending order (base classes' properties first) // and if there are more properties to be dumped put them in the stack if (!DumpedTopProperties(state, statesWithRemainingProperties)) { // dump all properties with negative order in class ascending order (derived classes' properties first) DumpRemainingProperties(statesWithRemainingProperties, statesWithTailProperties); // dump all properties with Order=int.MinValue in ascending order (derived classes' properties first) DumpTailProperties(statesWithTailProperties); // * if the object implements IEnumerable and the state allows it - dump the elements. state.DumpedCollection(classDumpData.DumpAttribute, true); } // we are done dumping state.Unindent(); } } if (buildScript && state.DumpScript != null) { script = DumpScriptCache.Add(this, objectType, classDumpData, state.DumpScript); } if (!buildScript) { if (isTopLevelObject) { Writer.Unindent(_indentLevel, _indentSize); } } else { if (script != null) { if (isTopLevelObject) { Writer.Indent(_indentLevel, _indentSize) .WriteLine(); } script(obj, classDumpData, this, state); } } // restore here the IsSubExpression flag as it have changed if obj is Expression and IsSubExpression==false. IsSubExpression = isSubExpressionStore; } }