void Introspect(object source, Field field) { if (IntrospectNullValue(source, field)) return; var sourceType = source.GetType(); if (IntrospectSimpleValue(source, field, sourceType)) return; if (SeenObjectBefore(source, field)) return; // handle a subset of dictionaries separately for terser printing if (IntrospectDictionaryWithSimpleKey(source as IDictionary, field, sourceType)) return; if (IntrospectIEnumerable(source, field)) return; IntrospectComplexType(source, field, sourceType); }
private bool SeenObjectBefore(object source, Field field) { Reference reference; if(seenBefore.TryGetValue(source, out reference)) { tokens.Add(Token.SeenBefore(field, reference)); return true; } else { seenBefore[source] = new Reference(referenceCounter++); return false; } }
private bool IntrospectIEnumerable(object source, Field field) { var enumerable = source as IEnumerable; if (enumerable == null) return false; Reference optionReferenceInfo; seenBefore.TryGetValue(source, out optionReferenceInfo); tokens.Add(new Token(TokenType.FieldnameWithTypeAndReference, field, null, optionReferenceInfo, source.GetType())); tokens.Add(StartEnumeration); int i = 0; foreach (var x in enumerable) { var outputFieldName = new Field(field.Name, ""+ i++); Introspect(x, outputFieldName); } tokens.Add(EndEnumeration); return true; }
bool IntrospectDictionaryWithSimpleKey(IDictionary source, Field field, Type sourceType) { if (source == null) return false; if(sourceType.GetGenericArguments().Length != 2) return false; IValueConverter handler; var keyType = sourceType.GetGenericArguments().First(); var isKeyTypeSimple = Configuration.TryGetValueConverter(keyType, out handler); if (!isKeyTypeSimple) return false; // print as enumerable which is more verbose tokens.Add(StartEnumeration); var keys = source.Keys; foreach (var key in keys) { var valueValue = source[key]; var keyValue = handler.Convert(key); var outputfieldName = new Field(field.Name, keyValue); Introspect(valueValue, outputfieldName); } tokens.Add(EndEnumeration); return true; }
bool IntrospectNullValue(object source, Field field) { if (source != null) return false; tokens.Add(new Token(TokenType.SimpleFieldValue, field, "null")); return true; }
bool IntrospectSimpleValue(object source, Field field, Type sourceType) { IValueConverter handler; if (!Configuration.TryGetValueConverter(sourceType, out handler)) return false; tokens.Add(new Token(TokenType.SimpleFieldValue, field, handler.Convert(source))); return true; }
void IntrospectComplexType(object source, Field field, Type sourceType) { Reference optionReferenceInfo; seenBefore.TryGetValue(source, out optionReferenceInfo); tokens.Add(new Token(TokenType.FieldnameWithTypeAndReference, field, null, optionReferenceInfo, sourceType)); tokens.Add(Startscope); ReflectionInfo reflection = ReflectFields(sourceType); for (int i = 0; i < reflection.RawReflectedFields.Count; i++) { var ffield = reflection.RawReflectedFields[i]; Introspect(ffield.GetValue(source), reflection.Fields[i]); } tokens.Add(Endscope); }
void IntrospectComplexType(object source, Field field, Type sourceType) { Reference optionReferenceInfo; seenBefore.TryGetValue(source, out optionReferenceInfo); tokens.Add(new Token(TokenType.FieldnameWithTypeAndReference, field, null, optionReferenceInfo, sourceType)); tokens.Add(Startscope); ReflectionInfo reflection = ReflectFields(sourceType); for (int i = 0; i < reflection.Fields.Length; i++) { Introspect(reflection.ValueProviders[i](source), reflection.Fields[i]); } tokens.Add(Endscope); }