Exemplo n.º 1
0
        private ComplexTypeMaterializer.Plan GetPlan(DataRecordInfo recordInfo)
        {
            ComplexTypeMaterializer.Plan[] planArray = this._lastPlans ?? (this._lastPlans = new ComplexTypeMaterializer.Plan[4]);
            int index1 = this._lastPlanIndex - 1;

            for (int index2 = 0; index2 < 4; ++index2)
            {
                index1 = (index1 + 1) % 4;
                if (planArray[index1] != null)
                {
                    if (planArray[index1].Key == recordInfo.RecordType)
                    {
                        this._lastPlanIndex = index1;
                        return(planArray[index1]);
                    }
                }
                else
                {
                    break;
                }
            }
            ObjectTypeMapping objectMapping = Util.GetObjectMapping(recordInfo.RecordType.EdmType, this._workspace);

            this._lastPlanIndex = index1;
            planArray[index1]   = new ComplexTypeMaterializer.Plan(recordInfo.RecordType, objectMapping, recordInfo.FieldMetadata);
            return(planArray[index1]);
        }
        internal StateManagerTypeMetadata(EdmType edmType, ObjectTypeMapping mapping)
        {
            this._typeUsage  = TypeUsage.Create(edmType);
            this._recordInfo = new DataRecordInfo(this._typeUsage);
            ReadOnlyMetadataCollection <EdmProperty> properties = TypeHelpers.GetProperties(edmType);

            this._members             = new StateManagerMemberMetadata[properties.Count];
            this._objectNameToOrdinal = new Dictionary <string, int>(properties.Count);
            this._cLayerNameToOrdinal = new Dictionary <string, int>(properties.Count);
            ReadOnlyMetadataCollection <EdmMember> metadataCollection = (ReadOnlyMetadataCollection <EdmMember>)null;

            if (Helper.IsEntityType(edmType))
            {
                metadataCollection = ((EntityTypeBase)edmType).KeyMembers;
            }
            for (int index = 0; index < this._members.Length; ++index)
            {
                EdmProperty           memberMetadata = properties[index];
                ObjectPropertyMapping memberMap      = (ObjectPropertyMapping)null;
                if (mapping != null)
                {
                    memberMap = mapping.GetPropertyMap(memberMetadata.Name);
                    if (memberMap != null)
                    {
                        this._objectNameToOrdinal.Add(memberMap.ClrProperty.Name, index);
                    }
                }
                this._cLayerNameToOrdinal.Add(memberMetadata.Name, index);
                this._members[index] = new StateManagerMemberMetadata(memberMap, memberMetadata, metadataCollection != null && metadataCollection.Contains((EdmMember)memberMetadata));
            }
        }
Exemplo n.º 3
0
        private bool InitializeTypeMappings()
        {
            foreach (var module in _server.Modules)
            {
                var mname = module.GetType().Name;
                foreach (var entMapping in module.EntityMappings)
                {
                    var typeDef = _model.GetTypeDef(entMapping.GraphQLType);
                    if (typeDef == null)
                    {
                        AddError($"Mapping target type {entMapping.GraphQLType.Name} is not registered; module {mname}");
                        continue;
                    }

                    if (!(typeDef is ObjectTypeDef objTypeDef))
                    {
                        AddError($"Invalid mapping target type {entMapping.GraphQLType.Name}, must be Object type; module {mname}");
                        continue;
                    }
                    var typeMapping = new ObjectTypeMapping(objTypeDef, entMapping.EntityType, entMapping.Expression);
                    RegisterTypeMapping(typeMapping);
                } // foreach mapping
            }
            // Add self-maps to all objects, including module-level Query, Mutation types
            foreach (var typeDef in _model.Types)
            {
                if (typeDef is ObjectTypeDef otd)
                {
                    var mappingExt = new ObjectTypeMapping(otd, otd.ClrType);
                    otd.Mappings.Add(mappingExt);
                }
            }
            return(!_model.HasErrors);
        }
Exemplo n.º 4
0
 private void RegisterTypeMapping(ObjectTypeMapping mapping)
 {
     // register in ObjectTypeDef
     mapping.TypeDef.Mappings.Add(mapping);
     // register in global dict by entity type
     if (!_model.EntityMappings.TryGetValue(mapping.EntityType, out var mapList))
     {
         mapList = new List <ObjectTypeMapping>();
         _model.EntityMappings[mapping.EntityType] = mapList;
     }
     mapList.Add(mapping);
 }
Exemplo n.º 5
0
        private void AssignResolversByFieldResolverAttribute(ObjectTypeMapping mapping)
        {
            var typeDef = mapping.TypeDef;

            foreach (var field in typeDef.Fields)
            {
                if (field.ClrMember == null)
                {
                    continue; //__typename has no clr member
                }
                var resAttr = GetAllAttributesAndAdjustments(field.ClrMember).Find <ResolverAttribute>();
                if (resAttr == null)
                {
                    continue;
                }
                var resolverType = resAttr.ResolverClass;
                if (resolverType != null)
                {
                    if (!typeDef.Module.ResolverClasses.Contains(resolverType))
                    {
                        AddError($"Field {typeDef.Name}.{field.Name}: target resolver class {resolverType.Name} is not registered with module. ");
                        continue;
                    }
                }
                // Get field res info and check if it's already mapped
                var methName     = resAttr.MethodName ?? field.ClrMember.Name;
                var resMethInfos = FindResolvers(methName, resolverType);
                switch (resMethInfos.Count)
                {
                case 1:
                    break;

                case 0:
                    AddError($"Field {typeDef.Name}.{field.Name}: failed to find resolver method {methName}. ");
                    continue; //next field

                default:
                    AddError($"Field {typeDef.Name}.{field.Name}: found more than one resolver method ({methName}).");
                    continue; //next field
                }
                // we have single matching resolver
                var resMethInfo = resMethInfos[0];
                VerifyFieldResolverMethod(field, resMethInfo);
                // get field resolver info and check if it is already mapped
                var fldRes = mapping.GetResolver(field);
                if (fldRes.IsMapped())
                {
                    AddError($"Field {typeDef.Name}.{field.Name}: failed to set resolver '{methName}', field is already mapped. ");
                    continue; //next field
                }
                fldRes.ResolverMethod = resMethInfo;
            } //foreach field
        }     //method
 private static Type GetDeclaringType(RelatedEnd relatedEnd)
 {
     if (relatedEnd.NavigationProperty != null)
     {
         EntityType        declaringEntityType = (EntityType)relatedEnd.NavigationProperty.DeclaringType;
         ObjectTypeMapping mapping             = System.Data.Common.Internal.Materialization.Util.GetObjectMapping(declaringEntityType, relatedEnd.WrappedOwner.Context.MetadataWorkspace);
         return(mapping.ClrType.ClrType);
     }
     else
     {
         return(relatedEnd.WrappedOwner.IdentityType);
     }
 }
 private void VerifyAllResolversAssigned(ObjectTypeMapping mapping)
 {
     foreach (var fres in mapping.FieldResolvers)
     {
         // so far we have only exec type to set, or post error
         if (fres.ResolverFunc == null && fres.ResolverMethod == null)
         {
             var fldName = fres.Field.Name;
             var typeDef = mapping.TypeDef;
             var fldRef  = $"'{typeDef.ClrType.Name}.{fldName}', mapping from (entity) type '{mapping.EntityType}', " +
                           $" (module '{typeDef.Module.Name}')";
             AddError($"Field '{fldName}' has no associated resolver or mapped entity field. Field: {fldRef}.");
         }
     } // foreach fres
 }
Exemplo n.º 8
0
 internal Plan(
     TypeUsage key,
     ObjectTypeMapping mapping,
     ReadOnlyCollection <FieldMetadata> fields)
 {
     this.Key        = key;
     this.ClrType    = DelegateFactory.GetConstructorDelegateForType((ClrComplexType)mapping.ClrType);
     this.Properties = new ComplexTypeMaterializer.PlanEdmProperty[fields.Count];
     for (int index = 0; index < this.Properties.Length; ++index)
     {
         FieldMetadata field   = fields[index];
         int           ordinal = field.Ordinal;
         this.Properties[index] = new ComplexTypeMaterializer.PlanEdmProperty(ordinal, mapping.GetPropertyMap(field.FieldType.Name).ClrProperty);
     }
 }
        internal StateManagerTypeMetadata(EdmType edmType, ObjectTypeMapping mapping)
        {
            DebugCheck.NotNull(edmType);
            Debug.Assert(
                Helper.IsEntityType(edmType) ||
                Helper.IsComplexType(edmType),
                "not Complex or EntityType");
            Debug.Assert(
                ReferenceEquals(mapping, null) ||
                ReferenceEquals(mapping.EdmType, edmType),
                "different EdmType instance");

            _typeUsage  = TypeUsage.Create(edmType);
            _recordInfo = new DataRecordInfo(_typeUsage);

            var members = TypeHelpers.GetProperties(edmType);

            _members             = new StateManagerMemberMetadata[members.Count];
            _objectNameToOrdinal = new Dictionary <string, int>(members.Count);
            _cLayerNameToOrdinal = new Dictionary <string, int>(members.Count);

            ReadOnlyMetadataCollection <EdmMember> keyMembers = null;

            if (Helper.IsEntityType(edmType))
            {
                keyMembers = ((EntityType)edmType).KeyMembers;
            }

            for (var i = 0; i < _members.Length; ++i)
            {
                var member = members[i];

                ObjectPropertyMapping memberMap = null;
                if (null != mapping)
                {
                    memberMap = mapping.GetPropertyMap(member.Name);
                    if (null != memberMap)
                    {
                        _objectNameToOrdinal.Add(memberMap.ClrProperty.Name, i); // olayer name
                    }
                }
                _cLayerNameToOrdinal.Add(member.Name, i); // clayer name

                // Determine whether this member is part of the identity of the entity.
                _members[i] = new StateManagerMemberMetadata(memberMap, member, ((null != keyMembers) && keyMembers.Contains(member)));
            }
        }
Exemplo n.º 10
0
        } //method

        private void AssignResolversFromCompiledMappingExpressions(ObjectTypeMapping mapping)
        {
            if (mapping.Expression == null)
            {
                return;
            }
            var entityPrm  = mapping.Expression.Parameters[0];
            var memberInit = mapping.Expression.Body as MemberInitExpression;

            if (memberInit == null)
            {
                AddError($"Invalid mapping expression for type '{mapping.EntityType}->{mapping.TypeDef.Name}'.");
                return;
            }
            foreach (var bnd in memberInit.Bindings)
            {
                var asmtBnd = bnd as MemberAssignment;
                if (asmtBnd == null)
                {
                    AddError($"Invalid mapping expression '{bnd}', expected assignment binding.");
                    continue;
                }
                var fldName  = bnd.Member.Name.FirstLower();
                var fieldDef = mapping.TypeDef.Fields[fldName];
                if (fieldDef == null)
                {
                    AddError($"Invalid assignment expression, target field '{fldName}' not found.");
                    continue;
                }
                // create lambda reading the source property
                var resInfo = mapping.GetResolver(fieldDef);
                if (resInfo == null)
                {
                    continue;
                }
                if (resInfo.IsMapped())
                {
                    AddError($"Resolver mapper by LINQ expression: field '{fieldDef}' is already mapped to a resolver.");
                    continue;
                }
                resInfo.ResolverFunc = CompileResolverExpression(entityPrm, asmtBnd.Expression);
            } //foreach bnd
        }
Exemplo n.º 11
0
        /// <summary>
        /// Given the type in the target space and the member name in the source space,
        /// get the corresponding member in the target space
        /// For e.g.  consider a Conceptual Type Foo with a member bar and a CLR type
        /// XFoo with a member YBar. If one has a reference to Foo one can
        /// invoke GetMember(Foo,"YBar") to retrieve the member metadata for bar
        /// </summary>
        /// <param name="type">The type in the target perspective</param>
        /// <param name="memberName">the name of the member in the source perspective</param>
        /// <param name="ignoreCase">true for case-insensitive lookup</param>
        /// <param name="outMember">returns the edmMember if a match is found</param>
        /// <returns>true if a match is found, otherwise false</returns>
        internal override bool TryGetMember(StructuralType type, String memberName, bool ignoreCase, out EdmMember outMember)
        {
            outMember = null;
            Map map = null;

            if (this.MetadataWorkspace.TryGetMap(type, DataSpace.OCSpace, out map))
            {
                ObjectTypeMapping objectTypeMap = map as ObjectTypeMapping;

                if (objectTypeMap != null)
                {
                    ObjectMemberMapping objPropertyMapping = objectTypeMap.GetMemberMapForClrMember(memberName, ignoreCase);
                    if (null != objPropertyMapping)
                    {
                        outMember = objPropertyMapping.EdmMember;
                        return(true);
                    }
                }
            }
            return(false);
        }
Exemplo n.º 12
0
        }     //method

        // those members that do not have binding expressions, try mapping props with the same name
        private void AssignResolversByEntityPropertyNameMatch(ObjectTypeMapping mapping)
        {
            var entityType     = mapping.EntityType;
            var allEntFldProps = entityType.GetFieldsProps();

            foreach (var fldDef in mapping.TypeDef.Fields)
            {
                var res = mapping.GetResolver(fldDef);
                if (res.IsMapped())
                {
                    continue; //already set
                }
                var        memberName = fldDef.Name;
                MemberInfo entMember  = allEntFldProps.Where(m => m.Name.Equals(memberName, StringComparison.OrdinalIgnoreCase))
                                        .FirstOrDefault();
                if (entMember == null)
                {
                    continue;
                }
                res.ResolverFunc = ExpressionHelper.CompileMemberReader(entMember);
            } //foreach fldDef
        }
Exemplo n.º 13
0
        private ObjectTypeDef BuildRootSchemaObject(string name, TypeRole typeRole, TypeRole moduleTypeRole)
        {
            var allModuleAggrTypes = _model.Types.OfType <ObjectTypeDef>()
                                     .Where(t => t.TypeRole == moduleTypeRole)
                                     .ToList();

            if (allModuleAggrTypes.Count == 0)
            {
                return(null);
            }
            // create root object (ex: Query type)
            var rootObjTypeDef = new ObjectTypeDef(name, null, GraphQLModelObject.EmptyAttributeList, null, typeRole);

            RegisterTypeDef(rootObjTypeDef);
            var mapping = new ObjectTypeMapping(rootObjTypeDef, null);

            rootObjTypeDef.Mappings.Add(mapping);
            // copy resolvers
            foreach (var aggrType in allModuleAggrTypes)
            {
                mapping.FieldResolvers.AddRange(aggrType.Mappings[0].FieldResolvers);
            }
            // collect all fields from collected resolvers
            var allFields = mapping.FieldResolvers.Select(fr => fr.Field).ToList();

            rootObjTypeDef.Fields.AddRange(allFields);
            // check for name duplicates
            var fieldNameDupes = rootObjTypeDef.Fields.Select(f => f.Name).GroupBy(fn => fn).Where(g => g.Count() > 1).ToList();

            if (fieldNameDupes.Count > 0)
            {
                string dupesAll = string.Join(",", fieldNameDupes.Select(g => g.Key));
                AddError($"Duplicate fields defined at top-level type {typeRole}, field names: {dupesAll}");
            }
            // important: re-assign Index value for all fields; we moved fields to aggregate Query, Mutation
            //  objects, so their indexes changed
            ReassignFieldIndexes(rootObjTypeDef);
            return(rootObjTypeDef);
        }
Exemplo n.º 14
0
        private Plan GetPlan(IExtendedDataRecord record, DataRecordInfo recordInfo)
        {
            Debug.Assert(null != record, "null IExtendedDataRecord");
            Debug.Assert(null != recordInfo, "null DataRecordInfo");
            Debug.Assert(null != recordInfo.RecordType, "null TypeUsage");

            Plan[] plans = _lastPlans ?? (_lastPlans = new Plan[MaxPlanCount]);

            // find an existing plan in circular buffer
            int index = _lastPlanIndex - 1;

            for (int i = 0; i < MaxPlanCount; ++i)
            {
                index = (index + 1) % MaxPlanCount;
                if (null == plans[index])
                {
                    break;
                }
                if (plans[index].Key == recordInfo.RecordType)
                {
                    _lastPlanIndex = index;
                    return(plans[index]);
                }
            }
            Debug.Assert(0 <= index, "negative index");
            Debug.Assert(index != _lastPlanIndex || (null == plans[index]), "index wrapped around");

            // create a new plan
            ObjectTypeMapping mapping = System.Data.Common.Internal.Materialization.Util.GetObjectMapping(recordInfo.RecordType.EdmType, _workspace);

            Debug.Assert(null != mapping, "null ObjectTypeMapping");

            Debug.Assert(Helper.IsComplexType(recordInfo.RecordType.EdmType),
                         "IExtendedDataRecord is not ComplexType");

            _lastPlanIndex = index;
            plans[index]   = new Plan(recordInfo.RecordType, mapping, recordInfo.FieldMetadata);
            return(plans[index]);
        }
Exemplo n.º 15
0
            internal Plan(TypeUsage key, ObjectTypeMapping mapping, System.Collections.ObjectModel.ReadOnlyCollection <FieldMetadata> fields)
            {
                Debug.Assert(null != mapping, "null ObjectTypeMapping");
                Debug.Assert(null != fields, "null FieldMetadata");

                Key = key;
                Debug.Assert(!Helper.IsEntityType(mapping.ClrType), "Expecting complex type");
                ClrType    = LightweightCodeGenerator.GetConstructorDelegateForType((ClrComplexType)mapping.ClrType);
                Properties = new PlanEdmProperty[fields.Count];

                int lastOrdinal = -1;

                for (int i = 0; i < Properties.Length; ++i)
                {
                    FieldMetadata field = fields[i];

                    Debug.Assert(unchecked ((uint)field.Ordinal) < unchecked ((uint)fields.Count), "FieldMetadata.Ordinal out of range of Fields.Count");
                    Debug.Assert(lastOrdinal < field.Ordinal, "FieldMetadata.Ordinal is not increasing");
                    lastOrdinal = field.Ordinal;

                    Properties[i] = new PlanEdmProperty(lastOrdinal, mapping.GetPropertyMap(field.FieldType.Name).ClrProperty);
                }
            }
Exemplo n.º 16
0
        internal static bool TryDetermineCSpaceModelType(Type type, MetadataWorkspace workspace, out EdmType modelEdmType)
        {
            Debug.Assert(null != workspace);
            Type nonNullabelType = TypeSystem.GetNonNullableType(type);

            // make sure the workspace knows about T
            workspace.ImplicitLoadAssemblyForType(nonNullabelType, System.Reflection.Assembly.GetCallingAssembly());
            ObjectItemCollection objectItemCollection = (ObjectItemCollection)workspace.GetItemCollection(DataSpace.OSpace);
            EdmType objectEdmType;

            if (objectItemCollection.TryGetItem <EdmType>(nonNullabelType.FullName, out objectEdmType))
            {
                Map map;
                if (workspace.TryGetMap(objectEdmType, DataSpace.OCSpace, out map))
                {
                    ObjectTypeMapping objectMapping = (ObjectTypeMapping)map;
                    modelEdmType = objectMapping.EdmType;
                    return(true);
                }
            }
            modelEdmType = null;
            return(false);
        }
Exemplo n.º 17
0
        }     //method

        // we try to match field defined as method, by member/method name, even if GraphQL name is different; match: GraphQL ObjType.Member => Resolver.Member
        private void AssignResolversToMatchingResolverMethods(ObjectTypeMapping mapping)
        {
            var typeDef = mapping.TypeDef;

            foreach (var field in typeDef.Fields)
            {
                var fRes = mapping.GetResolver(field);
                if (fRes.IsMapped())
                {
                    continue;
                }
                if (field.ClrMember == null)
                {
                    continue; //__typename has no clr member
                }
                var methName      = field.ClrMember.Name;
                var resolverInfos = _allResolverMethods
                                    .Where(res => res.Module == mapping.TypeDef.Module) // in the same module!
                                    .Where(res => res.Method.Name.Equals(methName, StringComparison.OrdinalIgnoreCase)).ToList();
                switch (resolverInfos.Count)
                {
                case 0:
                    continue; // no match

                case 1:
                    break;

                default:
                    AddError($"Field {typeDef.Name}.{field.Name}: found more than one resolver method ({methName}).");
                    continue;
                } //switch
                var resInfo = resolverInfos[0];
                VerifyFieldResolverMethod(field, resInfo);
                var fldRes = mapping.GetResolver(field);
                fldRes.ResolverMethod = resInfo;
            } //foreach field
        }     //method
        internal override bool TryGetMember(
            StructuralType type,
            string memberName,
            bool ignoreCase,
            out EdmMember outMember)
        {
            outMember = (EdmMember)null;
            MappingBase map = (MappingBase)null;

            if (this.MetadataWorkspace.TryGetMap((GlobalItem)type, DataSpace.OCSpace, out map))
            {
                ObjectTypeMapping objectTypeMapping = map as ObjectTypeMapping;
                if (objectTypeMapping != null)
                {
                    ObjectMemberMapping memberMapForClrMember = objectTypeMapping.GetMemberMapForClrMember(memberName, ignoreCase);
                    if (memberMapForClrMember != null)
                    {
                        outMember = memberMapForClrMember.EdmMember;
                        return(true);
                    }
                }
            }
            return(false);
        }
Exemplo n.º 19
0
        public static ObjectTypeMapping FindMapping(this TypeDefBase typeDef, Type fromType)
        {
            ObjectTypeMapping mapping = null;

            switch (typeDef)
            {
            case ObjectTypeDef otd:
                mapping = otd.FindObjectTypeMapping(fromType);
                break;

            case InterfaceTypeDef itd:
                mapping = FindObjectTypeMapping(itd.PossibleTypes, fromType);
                break;

            case UnionTypeDef utd:
                mapping = FindObjectTypeMapping(utd.PossibleTypes, fromType);
                break;

            default:
                // should never happen
                throw new Exception($"FATAL: Invalid target type kind {typeDef.Kind}, type {typeDef.Name}");
            }
            return(mapping);
        }
            internal Plan(TypeUsage key, ObjectTypeMapping mapping, ReadOnlyCollection <FieldMetadata> fields)
            {
                DebugCheck.NotNull(mapping);
                DebugCheck.NotNull(fields);

                Key = key;
                Debug.Assert(!Helper.IsEntityType(mapping.ClrType), "Expecting complex type");
                ClrType    = DelegateFactory.GetConstructorDelegateForType((ClrComplexType)mapping.ClrType);
                Properties = new PlanEdmProperty[fields.Count];

                var lastOrdinal = -1;

                for (var i = 0; i < Properties.Length; ++i)
                {
                    var field = fields[i];

                    Debug.Assert(
                        unchecked ((uint)field.Ordinal) < unchecked ((uint)fields.Count), "FieldMetadata.Ordinal out of range of Fields.Count");
                    Debug.Assert(lastOrdinal < field.Ordinal, "FieldMetadata.Ordinal is not increasing");
                    lastOrdinal = field.Ordinal;

                    Properties[i] = new PlanEdmProperty(lastOrdinal, mapping.GetPropertyMap(field.FieldType.Name).ClrProperty);
                }
            }
Exemplo n.º 21
0
        // setup resolvers having [ResolvesField] attribute
        private void AssignResolversByMethodsResolvesFieldAttribute(IList <ObjectTypeDef> types)
        {
            // go thru resolver classes, find methods with ResolvesField attr
            foreach (var resMethInfo in _allResolverMethods)
            {
                var resAttr = resMethInfo.ResolvesAttribute;
                if (resAttr == null)
                {
                    continue;
                }
                var      module    = resMethInfo.Module;
                var      fieldName = resAttr.FieldName.FirstLower();
                FieldDef field     = null;
                var      typeDefs  = types.Where(t => t.Module == resMethInfo.Module).OfType <ObjectTypeDef>();
                // check target type
                if (resAttr.TargetType != null)
                {
                    var typeDef = typeDefs.FirstOrDefault(td => td.ClrType == resAttr.TargetType);
                    if (typeDef == null)
                    {
                        AddError($"Resolver method '{resMethInfo}': target type '{resAttr.TargetType}' not registered or is not Object type.");
                        continue;
                    }
                    // match field
                    field = typeDef.Fields.FirstOrDefault(f => f.Name == fieldName);
                    if (field == null)
                    {
                        AddError($"Resolver method '{resMethInfo}': target field '{fieldName}' not found "
                                 + $"on type '{resAttr.TargetType}'.");
                        continue;
                    }
                }
                else
                {
                    // TargetType is null - find match by name only
                    var fields = typeDefs.SelectMany(t => t.Fields).Where(f => f.Name == fieldName).ToList();
                    switch (fields.Count)
                    {
                    case 1:
                        field = fields[0];
                        break;

                    case 0:
                        AddError($"Resolver method '{resMethInfo}': target field '{fieldName}' not found on any object type.");
                        continue;

                    default:
                        AddError($"Resolver method '{resMethInfo}': multipe target fields '{fieldName}' found on Object types.");
                        continue;
                    }
                }
                // We have a field; verify method is compatible
                VerifyFieldResolverMethod(field, resMethInfo);
                // get parent arg type and find mapping
                var objTypeDef            = (ObjectTypeDef)field.OwnerType;
                ObjectTypeMapping mapping = null;
                switch (objTypeDef.TypeRole)
                {
                case TypeRole.ModuleQuery:
                case TypeRole.ModuleMutation:
                case TypeRole.ModuleSubscription:
                    mapping = objTypeDef.Mappings[0];
                    break;

                case TypeRole.Data:
                    var prms = resMethInfo.Method.GetParameters();
                    if (prms.Length < 2)
                    {
                        AddError($"Resolver method '{resMethInfo}', expected at least 2 parameters - field context and parent entity.");
                        continue;
                    }
                    var parentEntType = prms[1].ParameterType;
                    mapping = objTypeDef.Mappings.FirstOrDefault(m => m.EntityType.IsAssignableFrom(parentEntType));
                    if (mapping == null)
                    {
                        AddError($"Resolver method '{resMethInfo}', parent entity argument type '{parentEntType}' is not mapped to output GraphQL type '{objTypeDef.Name}'.");
                        continue;
                    }
                    break;

                default:
                    AddError($"Resolver method '{resMethInfo}', invalid target GraphQL type: '{objTypeDef.Name}'.");
                    continue;
                }//switch
                var fldResolver = mapping.GetResolver(field);
                if (fldResolver == null)
                {
                    AddError($"Resolver method '{resMethInfo}', failed to match to field resolver in type '{objTypeDef.Name}'.");
                    continue;
                }
                if (fldResolver.ResolverMethod != null)
                {
                    AddError($"Field '{fldResolver.Field}': more than one resolver method specified.");
                    continue;
                }
                fldResolver.ResolverMethod = resMethInfo; //assign resolver
            } //foreach resMeth
        } //method
Exemplo n.º 22
0
        //HashSet<string> _keys = new HashSet<string>();

        public OutputObjectScope(RequestPath path, object entity, ObjectTypeMapping mapping)
        {
            Path    = path;
            Entity  = entity;
            Mapping = mapping;
        }
        // <summary>
        // Retrieves a mapping to CLR type for the given EDM type. Assumes the MetadataWorkspace has no
        // </summary>
        internal static ObjectTypeMapping GetObjectMapping(EdmType type, MetadataWorkspace workspace)
        {
            // Check if the workspace has cspace item collection registered with it. If not, then its a case
            // of public materializer trying to create objects from PODR or EntityDataReader with no context.
            ItemCollection collection;

            if (workspace.TryGetItemCollection(DataSpace.CSpace, out collection))
            {
                return((ObjectTypeMapping)workspace.GetMap(type, DataSpace.OCSpace));
            }
            else
            {
                EdmType ospaceType;
                EdmType cspaceType;
                // If its a case of EntityDataReader with no context, the typeUsage which is passed in must contain
                // a cspace type. We need to look up an OSpace type in the ospace item collection and then create
                // ocMapping
                if (type.DataSpace
                    == DataSpace.CSpace)
                {
                    // if its a primitive type, then the names will be different for CSpace type and OSpace type
                    if (Helper.IsPrimitiveType(type))
                    {
                        ospaceType = workspace.GetMappedPrimitiveType(((PrimitiveType)type).PrimitiveTypeKind, DataSpace.OSpace);
                    }
                    else
                    {
                        // Metadata will throw if there is no item with this identity present.
                        // Is this exception fine or does object materializer code wants to wrap and throw a new exception
                        ospaceType = workspace.GetItem <EdmType>(type.FullName, DataSpace.OSpace);
                    }
                    cspaceType = type;
                }
                else
                {
                    // In case of PODR, there is no cspace at all. We must create a fake ocmapping, with ospace types
                    // on both the ends
                    ospaceType = type;
                    cspaceType = type;
                }

                // This condition must be hit only when someone is trying to materialize a legacy data reader and we
                // don't have the CSpace metadata.
                if (!Helper.IsPrimitiveType(ospaceType) &&
                    !Helper.IsEntityType(ospaceType) &&
                    !Helper.IsComplexType(ospaceType))
                {
                    throw new NotSupportedException(Strings.Materializer_UnsupportedType);
                }

                ObjectTypeMapping typeMapping;

                if (Helper.IsPrimitiveType(ospaceType))
                {
                    typeMapping = new ObjectTypeMapping(ospaceType, cspaceType);
                }
                else
                {
                    typeMapping = DefaultObjectMappingItemCollection.LoadObjectMapping(cspaceType, ospaceType, null);
                }

                return(typeMapping);
            }
        }