Esempio n. 1
0
        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));
        }