/// <summary> /// Inspects the provided type and generates a type expression to represent it in the object grpah. /// </summary> /// <param name="typeToCheck">The complete type specification to check.</param> /// <param name="typeDefinition">An optional expression declaration to use as a set of overrides on the type provided.</param> /// <returns>GraphFieldOptions.</returns> public static GraphTypeExpression GenerateTypeExpression(Type typeToCheck, IGraphTypeExpressionDeclaration typeDefinition = null) { Validation.ThrowIfNull(typeToCheck, nameof(typeToCheck)); if (typeDefinition?.TypeWrappers != null) { typeToCheck = GraphValidation.EliminateWrappersFromCoreType( typeToCheck, eliminateEnumerables: true, eliminateTask: true, eliminateNullableT: true); return(new GraphTypeExpression(typeToCheck.FriendlyName(), typeDefinition.TypeWrappers)); } // strip out Task{T} before doin any type inspections typeToCheck = GraphValidation.EliminateWrappersFromCoreType( typeToCheck, eliminateEnumerables: false, eliminateTask: true, eliminateNullableT: false); var hasDefinedDefaultValue = typeDefinition?.HasDefaultValue ?? false; List <MetaGraphTypes> wrappers = new List <MetaGraphTypes>(); if (GraphValidation.IsValidListType(typeToCheck)) { // auto generated type expressions will always allow for a nullable list (since class references can be null) // unwrap any nested lists as necessary: e.g. IEnumerable<IEnumerable<IEnumerable<T>>> while (true) { var unwrappedType = EliminateNextWrapperFromCoreType( typeToCheck, eliminateEnumerables: true, eliminateTask: false, eliminateNullableT: false); if (unwrappedType == typeToCheck) { break; } wrappers.Add(MetaGraphTypes.IsList); typeToCheck = unwrappedType; } if (!hasDefinedDefaultValue && GraphValidation.IsNotNullable(typeToCheck)) { wrappers.Add(MetaGraphTypes.IsNotNull); } } else if (!hasDefinedDefaultValue && GraphValidation.IsNotNullable(typeToCheck)) { wrappers.Add(MetaGraphTypes.IsNotNull); } typeToCheck = EliminateWrappersFromCoreType( typeToCheck, eliminateEnumerables: false, eliminateTask: false, eliminateNullableT: true); return(new GraphTypeExpression(typeToCheck.FriendlyName(), wrappers)); }