ReflectionServiceBase<TSettings>
public abstract class ReflectionServiceBase<TSettings> : IReflectionService where TSettings : JsonSchemaGeneratorSettings
The default reflection service implementation.
using Namotion.Reflection;
using NJsonSchema.Annotations;
using System;
using System.Collections;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
namespace NJsonSchema.Generation
{
[System.Runtime.CompilerServices.NullableContext(1)]
[System.Runtime.CompilerServices.Nullable(0)]
public abstract class ReflectionServiceBase<[System.Runtime.CompilerServices.Nullable(0)] TSettings> : IReflectionService where TSettings : JsonSchemaGeneratorSettings
{
[return: System.Runtime.CompilerServices.Nullable(new byte[] {
1,
1,
2
})]
public abstract Func<object, string> GetEnumValueConverter(TSettings settings);
public abstract void GenerateProperties(JsonSchema schema, ContextualType contextualType, TSettings settings, JsonSchemaGenerator schemaGenerator, JsonSchemaResolver schemaResolver);
public abstract string GetPropertyName(ContextualAccessorInfo accessorInfo, JsonSchemaGeneratorSettings settings);
public JsonTypeDescription GetDescription(ContextualType contextualType, ReferenceTypeNullHandling defaultReferenceTypeNullHandling, TSettings settings)
{
Type type = contextualType.get_OriginalType();
bool isNullable = IsNullable(contextualType, defaultReferenceTypeNullHandling);
JsonSchemaTypeAttribute contextOrTypeAttribute = AttributeExtensions.GetContextOrTypeAttribute<JsonSchemaTypeAttribute>(contextualType, true);
if (contextOrTypeAttribute != null) {
type = contextOrTypeAttribute.Type;
contextualType = ContextualTypeExtensions.ToContextualType(type);
if (contextOrTypeAttribute.IsNullableRaw.HasValue)
isNullable = contextOrTypeAttribute.IsNullableRaw.Value;
}
JsonSchemaAttribute contextOrTypeAttribute2 = AttributeExtensions.GetContextOrTypeAttribute<JsonSchemaAttribute>(contextualType, true);
if (contextOrTypeAttribute2 != null) {
JsonObjectType jsonType = (contextOrTypeAttribute2.Type != 0) ? contextOrTypeAttribute2.Type : JsonObjectType.Object;
string format = (!string.IsNullOrEmpty(contextOrTypeAttribute2.Format)) ? contextOrTypeAttribute2.Format : null;
return JsonTypeDescription.Create(contextualType, jsonType, isNullable, format);
}
return GetDescription(contextualType, settings, type, isNullable, defaultReferenceTypeNullHandling);
}
protected virtual JsonTypeDescription GetDescription(ContextualType contextualType, TSettings settings, Type originalType, bool isNullable, ReferenceTypeNullHandling defaultReferenceTypeNullHandling)
{
if (originalType.IsEnum)
return JsonTypeDescription.CreateForEnumeration(contextualType, IsStringEnum(contextualType, settings) ? JsonObjectType.String : JsonObjectType.Integer, false);
if (originalType == typeof(short) || originalType == typeof(uint) || originalType == typeof(ushort))
return JsonTypeDescription.Create(contextualType, JsonObjectType.Integer, false, null);
if (originalType == typeof(int))
return JsonTypeDescription.Create(contextualType, JsonObjectType.Integer, false, "int32");
if (originalType == typeof(long))
return JsonTypeDescription.Create(contextualType, JsonObjectType.Integer, false, "int64");
if (originalType == typeof(ulong))
return JsonTypeDescription.Create(contextualType, JsonObjectType.Integer, false, "uint64");
if (originalType == typeof(double))
return JsonTypeDescription.Create(contextualType, JsonObjectType.Number, false, "double");
if (originalType == typeof(float))
return JsonTypeDescription.Create(contextualType, JsonObjectType.Number, false, "float");
if (originalType == typeof(decimal))
return JsonTypeDescription.Create(contextualType, JsonObjectType.Number, false, "decimal");
if (originalType == typeof(bool))
return JsonTypeDescription.Create(contextualType, JsonObjectType.Boolean, false, null);
if (originalType == typeof(string) || originalType == typeof(Type))
return JsonTypeDescription.Create(contextualType, JsonObjectType.String, isNullable, null);
if (originalType == typeof(char))
return JsonTypeDescription.Create(contextualType, JsonObjectType.String, false, null);
if (originalType == typeof(Guid))
return JsonTypeDescription.Create(contextualType, JsonObjectType.String, false, "guid");
if (originalType == typeof(DateTime) || originalType == typeof(DateTimeOffset) || originalType.FullName == "NodaTime.OffsetDateTime" || originalType.FullName == "NodaTime.LocalDateTime" || originalType.FullName == "NodaTime.ZonedDateTime" || originalType.FullName == "NodaTime.Instant")
return JsonTypeDescription.Create(contextualType, JsonObjectType.String, false, "date-time");
if (originalType == typeof(TimeSpan) || originalType.FullName == "NodaTime.Duration")
return JsonTypeDescription.Create(contextualType, JsonObjectType.String, false, "duration");
string fullName = originalType.FullName;
if ((fullName == "NodaTime.LocalDate" || fullName == "System.DateOnly") ? true : false)
return JsonTypeDescription.Create(contextualType, JsonObjectType.String, false, "date");
fullName = originalType.FullName;
if ((fullName == "NodaTime.LocalTime" || fullName == "System.TimeOnly") ? true : false)
return JsonTypeDescription.Create(contextualType, JsonObjectType.String, false, "time");
if (originalType == typeof(Uri))
return JsonTypeDescription.Create(contextualType, JsonObjectType.String, isNullable, "uri");
if (originalType == typeof(byte))
return JsonTypeDescription.Create(contextualType, JsonObjectType.Integer, false, "byte");
if (originalType == typeof(byte[]))
return JsonTypeDescription.Create(contextualType, JsonObjectType.String, isNullable, "byte");
if (originalType.FullName == "Newtonsoft.Json.Linq.JArray")
return JsonTypeDescription.Create(contextualType, JsonObjectType.Array, isNullable, null);
if (originalType.FullName == "Newtonsoft.Json.Linq.JToken" || originalType.FullName == "Newtonsoft.Json.Linq.JObject" || originalType.FullName == "System.Dynamic.ExpandoObject" || originalType.FullName == "System.Text.Json.JsonElement" || originalType == typeof(object))
return JsonTypeDescription.Create(contextualType, JsonObjectType.None, isNullable, null);
if (IsBinary(contextualType)) {
if (settings.SchemaType == SchemaType.Swagger2)
return JsonTypeDescription.Create(contextualType, JsonObjectType.File, isNullable, null);
return JsonTypeDescription.Create(contextualType, JsonObjectType.String, isNullable, "binary");
}
if (contextualType.get_IsNullableType()) {
JsonTypeDescription description = GetDescription(contextualType.get_OriginalGenericArguments()[0], defaultReferenceTypeNullHandling, settings);
description.IsNullable = true;
return description;
}
if (IsDictionaryType(contextualType))
return JsonTypeDescription.CreateForDictionary(contextualType, JsonObjectType.Object, isNullable);
if (IsIAsyncEnumerableType(contextualType) || IsArrayType(contextualType))
return JsonTypeDescription.Create(contextualType, JsonObjectType.Array, isNullable, null);
return JsonTypeDescription.Create(contextualType, JsonObjectType.Object, isNullable, null);
}
public virtual bool IsNullable(ContextualType contextualType, ReferenceTypeNullHandling defaultReferenceTypeNullHandling)
{
if (EnumerableExtensions.FirstAssignableToTypeNameOrDefault<Attribute>(AttributeExtensions.GetContextAttributes(contextualType, true), "NotNullAttribute", 0) != null)
return false;
if (EnumerableExtensions.FirstAssignableToTypeNameOrDefault<Attribute>(AttributeExtensions.GetContextAttributes(contextualType, true), "CanBeNullAttribute", 0) != null)
return true;
if ((int)contextualType.get_Nullability() != 0)
return (int)contextualType.get_Nullability() == 2;
if (!(contextualType.get_Type() != typeof(string)) || !contextualType.get_TypeInfo().IsValueType)
return defaultReferenceTypeNullHandling != ReferenceTypeNullHandling.NotNull;
return false;
}
public virtual bool IsStringEnum(ContextualType contextualType, TSettings settings)
{
if (!contextualType.get_TypeInfo().IsEnum)
return false;
if (HasStringEnumConverter(contextualType))
return true;
return false;
}
protected virtual bool IsBinary(ContextualType contextualType)
{
if (contextualType.get_Name() == "IFormFile")
return true;
TypeInfo typeInfo = contextualType.get_TypeInfo();
if (typeInfo.IsArray || typeInfo.IsPrimitive)
return false;
if (contextualType.get_Name() == "HttpPostedFile")
return true;
if (TypeExtensions.IsAssignableToTypeName(contextualType, "HttpPostedFileBase", 0))
return true;
Type[] interfaces = typeInfo.GetInterfaces();
foreach (Type type in interfaces) {
if (type.Name == "IFormFile")
return true;
}
return false;
}
private static bool IsIAsyncEnumerableType(ContextualType contextualType)
{
return contextualType.get_Name() == "IAsyncEnumerable`1";
}
protected virtual bool IsArrayType(ContextualType contextualType)
{
if (IsDictionaryType(contextualType))
return false;
if (contextualType.get_Name() == "ObservableCollection`1")
return true;
if (!contextualType.get_Type().IsArray) {
if (Enumerable.Contains<Type>(contextualType.get_TypeInfo().ImplementedInterfaces, typeof(IEnumerable))) {
if (!(contextualType.get_TypeInfo().BaseType == (Type)null))
return !Enumerable.Contains<Type>(contextualType.get_TypeInfo().BaseType.GetTypeInfo().ImplementedInterfaces, typeof(IEnumerable));
return true;
}
return false;
}
return true;
}
protected virtual bool IsDictionaryType(ContextualType contextualType)
{
string name = contextualType.get_Name();
if ((name == "IDictionary`2" || name == "IReadOnlyDictionary`2") ? true : false)
return true;
if (Enumerable.Contains<Type>(contextualType.get_TypeInfo().ImplementedInterfaces, typeof(IDictionary))) {
if (!(contextualType.get_TypeInfo().BaseType == (Type)null))
return !Enumerable.Contains<Type>(contextualType.get_TypeInfo().BaseType.GetTypeInfo().ImplementedInterfaces, typeof(IDictionary));
return true;
}
return false;
}
private static bool HasStringEnumConverter(ContextualType contextualType)
{
dynamic val = null;
foreach (Attribute contextOrTypeAttribute in AttributeExtensions.GetContextOrTypeAttributes(contextualType, true)) {
if (contextOrTypeAttribute.GetType().Name == "JsonConverterAttribute") {
val = contextOrTypeAttribute;
break;
}
}
dynamic val2 = val != null;
if ((val2 ? false : true) ? val2 : (val2 & ObjectExtensions.HasProperty(val, "ConverterType"))) {
Type type = val?.ConverterType as Type;
if ((object)type != null) {
if (!TypeExtensions.IsAssignableToTypeName(type, "StringEnumConverter", 0))
return TypeExtensions.IsAssignableToTypeName(type, "System.Text.Json.Serialization.JsonStringEnumConverter", 1);
return true;
}
}
return false;
}
JsonTypeDescription IReflectionService.GetDescription(ContextualType contextualType, ReferenceTypeNullHandling defaultReferenceTypeNullHandling, JsonSchemaGeneratorSettings settings)
{
return GetDescription(contextualType, defaultReferenceTypeNullHandling, (TSettings)settings);
}
JsonTypeDescription IReflectionService.GetDescription(ContextualType contextualType, JsonSchemaGeneratorSettings settings)
{
return GetDescription(contextualType, settings.DefaultReferenceTypeNullHandling, (TSettings)settings);
}
bool IReflectionService.IsStringEnum(ContextualType contextualType, JsonSchemaGeneratorSettings settings)
{
return IsStringEnum(contextualType, (TSettings)settings);
}
[return: System.Runtime.CompilerServices.Nullable(new byte[] {
1,
1,
2
})]
Func<object, string> IReflectionService.GetEnumValueConverter(JsonSchemaGeneratorSettings settings)
{
return GetEnumValueConverter((TSettings)settings);
}
void IReflectionService.GenerateProperties(JsonSchema schema, ContextualType contextualType, JsonSchemaGeneratorSettings settings, JsonSchemaGenerator schemaGenerator, JsonSchemaResolver schemaResolver)
{
GenerateProperties(schema, contextualType, (TSettings)settings, schemaGenerator, schemaResolver);
}
}
}