private async Task <object> AugmentInternal( object obj, Type type, Action <IState> addState, Action <AugmentationContext, object> configure, object configureState) { var tiw = TypeInfoResolver.ResolveTypeInfo(type); if (tiw.IsPrimitive) { return(obj); } var alwaysBuild = tiw.IsWrapper || configure != null; var typeConfiguration = ResolveTypeConfiguration(tiw.Type, alwaysBuild); if (typeConfiguration == null && configure == null) { // No configuration return(obj); } var state = await CreateDictionaryAndAddStateAsync(addState, obj); var context = new AugmentationContext(obj, typeConfiguration, state); if (tiw.IsArray) { var asEnumerable = obj as IEnumerable; var list = (obj as IList) != null ? new List <object>((obj as IList).Count) : new List <object>(); Debug.Assert(asEnumerable != null, "asEnumerable != null"); foreach (var item in asEnumerable) { // We'll reuse the context. context.Object = item; list.Add(AugmentOne(obj, configure, configureState, tiw, context)); } return(list); } else if (tiw.IsWrapper && ReflectionHelper.IsEnumerableOrArrayType((((AugmenterWrapper)obj).Object).GetType(), out var elementType)) { context.EphemeralTypeConfiguration = ((AugmenterWrapper)obj).TypeConfiguration; obj = (((AugmenterWrapper)obj).Object); tiw = TypeInfoResolver.ResolveTypeInfo(elementType); var asEnumerable = obj as IEnumerable; var list = (obj as IList) != null ? new List <object>((obj as IList).Count) : new List <object>(); foreach (var item in asEnumerable) { // We'll reuse the context. context.Object = item; list.Add(AugmentOne(obj, configure, configureState, tiw, context)); } return(list); } else { return(AugmentOne(obj, configure, configureState, tiw, context)); } }
private static TypeConfiguration CreateConfigurationWithPropertiesOnly(Type baseType) { var tc = new TypeConfiguration(baseType); foreach (var pi in baseType.GetTypeInfo().DeclaredProperties) { tc.Properties.Add( new APropertyInfo(pi, TypeInfoResolver.ResolveTypeInfo(pi.PropertyType), null)); } return(tc); }
private void BuildOne(Context context, Type type) { if (context.Current != null && context.Current.Built) { return; } if (typeof(IEnumerable).GetTypeInfo().IsAssignableFrom(type.GetTypeInfo())) { return; } var allTypes = ReflectionHelper.IncludeBaseTypesAndImplementedInterface(type); foreach (var implType in allTypes) { var tc = _all.FirstOrDefault(t => t.Type == implType); if (tc != null) { context.EnsureCurrent(); context.AddBaseTypeConfiguration(tc); } else { var scoped = context.CreateScoped(null, implType); BuildOne(scoped, implType); if (!scoped.Empty) { context.EnsureCurrent(); context.AddBaseTypeConfiguration(scoped.Current); } else { context.AddBaseTypeConfiguration(CreateConfigurationWithPropertiesOnly(implType)); } } } var properties = type.GetTypeInfo().DeclaredProperties; foreach (var p in properties) { if (p.GetMethod.IsStatic) { continue; } var tiw = TypeInfoResolver.ResolveTypeInfo(p.PropertyType); if (tiw.IsPrimitive) { context.Properties.Add(new APropertyInfo(p, tiw, null)); } else if (tiw.Type == type) { // Detect self referencing type. context.EnsureCurrent(); context.Properties.Add(new APropertyInfo(p, tiw, context.Current)); } else { var nestedTypeConfiguration = _all.FirstOrDefault(c => c.Type == tiw.Type); if (tiw.IsWrapper || (context.Current != null && context.Current.NestedConfigurations.IsValueCreated && context.Current.NestedConfigurations.Value.TryGetValue(p, out _))) { nestedTypeConfiguration = nestedTypeConfiguration ?? new TypeConfiguration(type); } var scoped = context.CreateScoped( nestedTypeConfiguration, tiw.Type); BuildOne(scoped, tiw.Type); if (!scoped.Empty) { context.EnsureCurrent(); context.Properties.Add(new APropertyInfo(p, tiw, scoped.Current)); } else { context.Properties.Add(new APropertyInfo(p, tiw, null)); } } } if (!context.Empty) { context.EnsureCurrent(); context.Current.Properties.AddRange(context.Properties); } }