public static IServiceCollection RegisterExtensibleTypes( this IServiceCollection serviceCollection, TypeDescriptorPolicy defaultTypeDescriptorPolicy, IDictionary <Type, TypeDescriptorPolicy> typeDescriptorPolicyOverrides, Assembly[] assemblies) { serviceCollection.Configure <JsonSerializerOptions>(options => { var rootTypes = assemblies.SelectMany(a => a.GetTypes() .Where(t => { if (!typeof(IExtensible).IsAssignableFrom(t)) { return(false); } var extensionDataProperty = t.GetProperty(nameof(IExtensible.ExtensionData), typeof(ExtensionData)); return(extensionDataProperty != null && extensionDataProperty.DeclaringType == t); })) .Distinct(); var typeHierarchyAssemblyMapping = rootTypes.Select(t => new { Type = t, Assemblies = assemblies.Where(a => a.GetTypes().Any(t.IsAssignableFrom)).Distinct() }) .ToDictionary(o => o.Type, o => o.Assemblies); var typeMappings = new List <ITypeMappings>(); foreach (var(type, relatedAssemblies) in typeHierarchyAssemblyMapping) { if (!typeDescriptorPolicyOverrides.TryGetValue(type, out var typeDescriptorPolicy)) { typeDescriptorPolicy = defaultTypeDescriptorPolicy; } typeMappings.Add(SerializationHelpers.CreateConstructor <SerializationHelpers.DefaultTypeMappingsConstructorDelegate>(typeof(DefaultTypeMappings <>).MakeGenericType(type))(relatedAssemblies, typeDescriptorPolicy)); } options.Converters.Add(new ExtensibleJsonConverterFactory(typeMappings, defaultTypeDescriptorPolicy)); }); return(serviceCollection); }
/// <inheritdoc /> public override JsonConverter CreateConverter(Type typeToConvert, JsonSerializerOptions options) { var ctor = GetConstructor(_converterGenericType.MakeGenericType(typeToConvert)); var rootType = typeToConvert.GetProperty(nameof(IExtensible.ExtensionData), typeof(ExtensionData))?.DeclaringType; if (rootType == null) { throw new ArgumentException($"Cannot create an extensible JSON converter for type {typeToConvert} because it does not implement the {nameof(IExtensible)} interface."); } if (!_allTypeMappings.TryGetValue(rootType, out var typeMappings)) { // Type mapping not configured yet for one reason or another. // Configure type mappings by scanning assemblies where there are types that are assignable to the root type. var assemblies = AppDomain.CurrentDomain.GetAssemblies().Where(a => a.GetTypes().Any(rootType.IsAssignableFrom)); typeMappings = SerializationHelpers.CreateConstructor <SerializationHelpers.DefaultTypeMappingsConstructorDelegate>(typeof(DefaultTypeMappings <>).MakeGenericType(rootType))(assemblies, _defaultTypeDescriptor); _allTypeMappings[rootType] = typeMappings; } return(ctor(typeMappings)); }