/// <summary> /// Walk over a type to create a value. /// </summary> /// <param name="visitor">The type visitor object.</param> /// <param name="type">The type.</param> /// <typeparam name="T">The return type.</typeparam> /// <returns>A value.</returns> internal static T ApplyTypeVisitor <T>(ITypeVisitor <T> visitor, Type type) { if (type == BoolType) { return(visitor.VisitBool()); } if (type == ByteType) { return(visitor.VisitByte()); } if (type == ShortType) { return(visitor.VisitShort()); } if (type == UshortType) { return(visitor.VisitUshort()); } if (type == IntType) { return(visitor.VisitInt()); } if (type == UintType) { return(visitor.VisitUint()); } if (type == LongType) { return(visitor.VisitLong()); } if (type == UlongType) { return(visitor.VisitUlong()); } if (type == BigIntType) { return(visitor.VisitBigInteger()); } if (type == StringType) { return(visitor.VisitString()); } if (IsFixedIntegerType(type)) { return(visitor.VisitFixedInteger(type)); } if (IsOptionType(type)) { var t = type.GetGenericArguments()[0]; return(visitor.VisitOption(ty => ApplyTypeVisitor(visitor, ty), type, t)); } if (IsTupleType(type)) { var tleft = type.GetGenericArguments()[0]; var tright = type.GetGenericArguments()[1]; return(visitor.VisitTuple(ty => ApplyTypeVisitor(visitor, ty), type, tleft, tright)); } if (IsValueTupleType(type)) { var tleft = type.GetGenericArguments()[0]; var tright = type.GetGenericArguments()[1]; return(visitor.VisitValueTuple(ty => ApplyTypeVisitor(visitor, ty), type, tleft, tright)); } if (IsIListType(type)) { var t = type.GetGenericArguments()[0]; return(visitor.VisitList(ty => ApplyTypeVisitor(visitor, ty), type, t)); } if (IsIDictionaryType(type)) { var args = type.GetGenericArguments(); var tkey = args[0]; var tvalue = args[1]; return(visitor.VisitDictionary(ty => ApplyTypeVisitor(visitor, ty), type, tkey, tvalue)); } if (IsListType(type) || IsDictionaryType(type)) { throw new InvalidOperationException($"Unsupported object field type: {type}"); } // some class or struct var dict = new SortedDictionary <string, Type>(); foreach (var field in GetAllFields(type)) { dict[field.Name] = field.FieldType; } foreach (var property in GetAllProperties(type)) { dict[property.Name] = property.PropertyType; } return(visitor.VisitObject(t => ApplyTypeVisitor(visitor, t), type, dict)); }