public void GraphFieldAttribute_EmptyConstructor_TypeModifersAdded_PropertyCheck() { // simulate a user supplying "TypeModifiers = XXXX" in an attribute initializer // and esnure the logic of setting notnull list etc. var attrib = new GraphFieldAttribute(); Assert.AreEqual(TypeExpressions.Auto, attrib.TypeExpression); attrib.TypeExpression = TypeExpressions.IsNotNullList; CollectionAssert.AreEqual(GraphTypeExpression.RequiredList, attrib.TypeDefinition); }
public void GraphFieldAttribute_FieldNameConstructor_PropertyCheck() { var attrib = new GraphFieldAttribute("myFieldName"); Assert.AreEqual(GraphCollection.Types, attrib.FieldType); Assert.AreEqual(false, attrib.IsRootFragment); Assert.AreEqual(null, attrib.UnionTypeName); Assert.AreEqual("myFieldName", attrib.Template); Assert.AreEqual(TypeExpressions.Auto, attrib.TypeExpression); Assert.AreEqual(0, attrib.Types.Count); Assert.AreEqual(FieldResolutionMode.PerSourceItem, attrib.ExecutionMode); }
public void GraphFieldAttribute_EmptyConstructor_PropertyCheck() { var attrib = new GraphFieldAttribute(); Assert.AreEqual(GraphCollection.Types, attrib.FieldType); Assert.AreEqual(false, attrib.IsRootFragment); Assert.AreEqual(null, attrib.UnionTypeName); Assert.AreEqual(Constants.Routing.ACTION_METHOD_META_NAME, attrib.Template); Assert.AreEqual(TypeExpressions.Auto, attrib.TypeExpression); Assert.AreEqual(0, attrib.Types.Count); Assert.AreEqual(FieldResolutionMode.PerSourceItem, attrib.ExecutionMode); }
private IGraphResolver GetPropertyResolver(Type type, PropertyInfo property, GraphFieldAttribute memberAttribute) { if (!string.IsNullOrEmpty(memberAttribute?.Resolver)) { var resolverMethod = type.GetMethod(memberAttribute.Resolver); if (null == resolverMethod) { throw new GraphException($"The specified custom resolver method '{memberAttribute.Resolver}' is not defined in the type '{type}'"); } return(new MethodResolver(resolverMethod)); } return(new PropertyResolver(property)); }
private IGraphType GetPropertyGraphType(Type type, PropertyInfo property, GraphFieldAttribute memberAttribute) { var isPropertyEnumerable = property.PropertyType.IsEnumerable(out var propertyType); propertyType = propertyType ?? property.PropertyType; var isPropertyRequired = memberAttribute?.IsRequired; var unionTypeAttribute = _attributeAccessor.GetAttribute <UnionTypeAttribute>(property, false); var propertyGraphType = unionTypeAttribute == null ? GetGraphType(propertyType, isPropertyRequired, isPropertyEnumerable) : GetGraphType(unionTypeAttribute.Type, isPropertyRequired, isPropertyEnumerable, unionTypeAttribute.OtherTypes); if (unionTypeAttribute != null) { Array.ForEach(unionTypeAttribute.Types, it => GetGraphType(it, false, false)); } return(propertyGraphType); }
/// <summary> /// When overridden in a child class this method builds out the template according to its own individual requirements. /// </summary> protected override void ParseTemplateDefinition() { _fieldDeclaration = this.SingleAttributeOfTypeOrDefault <GraphFieldAttribute>(); // ------------------------------------ // Common Metadata // ------------------------------------ this.Route = this.GenerateFieldPath(); this.Mode = _fieldDeclaration?.ExecutionMode ?? FieldResolutionMode.PerSourceItem; this.Complexity = _fieldDeclaration?.Complexity; this.Description = this.SingleAttributeOfTypeOrDefault <DescriptionAttribute>()?.Description; var depreciated = this.SingleAttributeOfTypeOrDefault <DeprecatedAttribute>(); if (depreciated != null) { this.IsDeprecated = true; this.DeprecationReason = depreciated.Reason?.Trim(); } var objectType = GraphValidation.EliminateWrappersFromCoreType(this.DeclaredReturnType); var typeExpression = GraphValidation.GenerateTypeExpression(this.DeclaredReturnType, this); typeExpression = typeExpression.CloneTo(GraphTypeNames.ParseName(objectType, this.Parent.Kind)); // ------------------------------------ // Gather Possible Types and/or union definition // ------------------------------------ this.BuildUnionProxyInstance(); if (this.UnionProxy != null) { this.PossibleTypes = new List <Type>(this.UnionProxy.Types); } else { this.PossibleTypes = new List <Type>(); // the possible types attribte is optional but expects taht the concrete types are added // to the schema else where lest a runtime exception occurs of a missing graph type. var typesAttrib = this.SingleAttributeOfTypeOrDefault <PossibleTypesAttribute>(); if (typesAttrib != null) { foreach (var type in typesAttrib.PossibleTypes) { this.PossibleTypes.Add(type); } } // add any types decalred on the primary field declaration if (_fieldDeclaration != null) { foreach (var type in _fieldDeclaration.Types) { var strippedType = GraphValidation.EliminateWrappersFromCoreType(type); if (strippedType != null) { this.PossibleTypes.Add(strippedType); } } } if (objectType != null && !Validation.IsCastable <IGraphActionResult>(objectType) && GraphValidation.IsValidGraphType(objectType)) { this.PossibleTypes.Insert(0, objectType); } } this.PossibleTypes = this.PossibleTypes.Distinct().ToList(); // ------------------------------------ // Adjust the action result to the actual return type this field returns // ------------------------------------ if (Validation.IsCastable <IGraphActionResult>(objectType)) { if (this.UnionProxy != null) { // if a union was decalred preserve whatever modifer elements // were decalred but alter the return type to object (a known common element among all members of the union) objectType = typeof(object); } else if (_fieldDeclaration != null && _fieldDeclaration.Types.Count > 0) { objectType = _fieldDeclaration.Types[0]; typeExpression = GraphValidation.GenerateTypeExpression(objectType, this) .CloneTo(GraphTypeNames.ParseName(objectType, this.Parent.Kind)); objectType = GraphValidation.EliminateWrappersFromCoreType(objectType); } else if (this.PossibleTypes.Count > 0) { objectType = this.PossibleTypes[0]; typeExpression = GraphValidation.GenerateTypeExpression(objectType, this) .CloneTo(GraphTypeNames.ParseName(objectType, this.Parent.Kind)); objectType = GraphValidation.EliminateWrappersFromCoreType(objectType); } else { objectType = typeof(object); } } this.ObjectType = objectType; if (this.UnionProxy != null) { this.TypeExpression = typeExpression.CloneTo(this.UnionProxy.Name); } else { this.TypeExpression = typeExpression; } // ------------------------------------ // Async Requirements // ------------------------------------ this.IsAsyncField = Validation.IsCastable <Task>(this.DeclaredReturnType); // ------------------------------------ // Security Policies // ------------------------------------ _securityPolicies = FieldSecurityGroup.FromAttributeCollection(this.AttributeProvider); }