private static IEnumerable <FieldType> GetFieldsForFieldType(string remote, Introspection.TypeElement parentField) { FieldTypeResolver complexFieldTypeResolver = member => { if (!(member is RemoteLiteralGraphTypeMemberInfo literalMember)) { return(null); } if (!RemoteServerTypes.TryGetValue(remote, out var remoteTypes)) { return(null); } var schemaType = remoteTypes.FirstOrDefault(t => t.Name == literalMember.TypeName); var realType = literalMember.IsList ? typeof(ListGraphType <>).MakeGenericType(schemaType) : schemaType; return(new FieldType { Name = literalMember.Name, Type = realType, Resolver = LiteralGraphTypeHelpers.CreateFieldResolverFor(literalMember) }); }; var fields = parentField.Fields; if (fields == null) { return(new FieldType[] { }); } return(fields .Select(field => { return new RemoteLiteralGraphTypeMemberInfo { DeclaringTypeName = parentField.Name, Name = field.Name, Type = IntrospectionTypeToLiteralGraphTypeMemberInfoType(field.Type), TypeName = IntrospectionTypeToLiteralGraphTypeMemberInfoTypeName(field.Type), IsList = field.Type.Kind == TypeElementTypeKind.List, GetValueFn = ctx => { return ((JToken)ctx.Source)[field.Name].Value <object>(); } }; }) // TODO: handle unresolvable types (I'm looking at you UNION) .Where(member => member.Type != LiteralGraphTypeMemberInfoType.Unknown) .Select(member => LiteralGraphTypeHelpers.GetFieldTypeForMember(member, complexFieldTypeResolver)) .ToList()); }
private IEnumerable <FieldType> GetFields() { const BindingFlags bindingFlags = BindingFlags.Public | BindingFlags.Instance; var members = typeof(T) .GetProperties(bindingFlags) .AsEnumerable <MemberInfo>() .Union(typeof(T).GetFields(bindingFlags)) .Select(member => { var type = GetTypeForMemberInfo(member); return(new TypedLiteralGraphTypeMemberInfo { DeclaringTypeName = member.DeclaringType.FullName, Name = member.Name, Type = LiteralGraphTypeHelpers.GetLiteralGraphTypeMemberInfoTypeForType(type), IsList = IsListType(type), ActualType = type, GetValueFn = MakeGetValueFnForMemberInfo(member) }); }) .ToList(); FieldTypeResolver complexTypeResolver = member => { if (!(member is TypedLiteralGraphTypeMemberInfo typedMember)) { return(null); } var maybeActualType = typedMember.ActualType; if (maybeActualType == null) { return(null); } var literalGraphType = typedMember.IsList // IEnumerable<T> -> ListGraphType<LiteralGraphType<T>> ? typeof(ListGraphType <>).MakeGenericType(typeof(LiteralGraphType <>).MakeGenericType(GetListElementType(maybeActualType))) // T -> LiteralGraphType<T> : typeof(LiteralGraphType <>).MakeGenericType(maybeActualType); return(typeof(LiteralGraphTypeHelpers) .GetMethod(nameof(LiteralGraphTypeHelpers.CreateFieldType), BindingFlags.NonPublic | BindingFlags.Static) .MakeGenericMethod(literalGraphType) .Invoke(null, new[] { member }) as FieldType); }; return(members .Select(member => { try { // Find the field type var fieldType = LiteralGraphTypeHelpers.GetFieldTypeForMember(member, complexTypeResolver); return fieldType; } catch (Exception) { // TODO: log return null; } }) .ToList()); }
internal static FieldTypeResolver MakeFieldTypeResolverForMember(LiteralGraphTypeMemberInfo member, FieldTypeResolver complexFieldTypeResolver) { var type = member.Type; if (type == LiteralGraphTypeMemberInfoType.Complex) { return(complexFieldTypeResolver); } LiteralGraphTypeMemberInfoFieldTypeResolverMappings.TryGetValue(type, out var resolver); return(resolver); }
private static void PopulateTypeMapping(LiteralGraphTypeMemberInfoType type, Type actualType, FieldTypeResolver resolver) { LiteralGraphTypeMemberInfoTypeMappings.TryAdd(type, actualType); LiteralGraphTypeMemberInfoFieldTypeResolverMappings.TryAdd(type, resolver); }
internal static FieldType GetFieldTypeForMember(LiteralGraphTypeMemberInfo member, FieldTypeResolver complexFieldTypeResolver) { var memberFieldTypeMapKey = MakeMemberFieldTypeMapKey(member); // Try to find an existing FieldType for this member if (!MemberFieldTypeMappings.TryGetValue(memberFieldTypeMapKey, out var fieldType)) { // Throw a new FieldType in to indicate we're in the middle of resolving a FieldType fieldType = new FieldType(); MemberFieldTypeMappings.AddOrUpdate(memberFieldTypeMapKey, fieldType, (m, old) => fieldType); // Get the fieldtype resolver var fieldTypeResolver = GetFieldTypeResolverForMember(member, complexFieldTypeResolver); // Execute the resolver var actualFieldType = fieldTypeResolver(member); // Copy over fields PatchFieldType(fieldType, actualFieldType); } return(fieldType); }
internal static FieldTypeResolver GetFieldTypeResolverForMember(LiteralGraphTypeMemberInfo member, FieldTypeResolver complexFieldTypeResolver) { var memberFieldTypeResolverMapKey = MakeMemberFieldTypeResolverMapKey(member); // If we don't already know the fieldtype resolver for this member, we need to figure it out if (!MemberFieldTypeResolverMappings.TryGetValue(memberFieldTypeResolverMapKey, out var fieldTypeResolver) || fieldTypeResolver == null) { // Try to create a new field type resolver fieldTypeResolver = MakeFieldTypeResolverForMember(member, complexFieldTypeResolver); if (fieldTypeResolver == null) { return(null); } // Save the resolver MemberFieldTypeResolverMappings.AddOrUpdate(memberFieldTypeResolverMapKey, fieldTypeResolver, (m, old) => fieldTypeResolver); } return(fieldTypeResolver); }