/// <summary> /// Initializes a new instance of the <see cref="ObcSerializerBase"/> class. /// </summary> /// <param name="serializationConfigurationType">The serialization configuration type to use.</param> protected ObcSerializerBase( SerializationConfigurationType serializationConfigurationType) { if (serializationConfigurationType == null) { throw new ArgumentNullException(nameof(serializationConfigurationType)); } this.SerializationConfigurationType = serializationConfigurationType; this.SerializationConfiguration = SerializationConfigurationManager.GetOrAddSerializationConfiguration(serializationConfigurationType); }
/// <summary> /// Gets an existing, fully initialized serialization configuration or creates and fully initializes a new one if /// one does not already exist for the specified serialization configuration type. /// </summary> /// <param name="serializationConfigurationType">The serialization configuration type.</param> /// <returns> /// An initialized instance of the specified serialization configuration type. /// </returns> public static SerializationConfigurationBase GetOrAddSerializationConfiguration( SerializationConfigurationType serializationConfigurationType) { if (serializationConfigurationType == null) { throw new ArgumentNullException(nameof(serializationConfigurationType)); } var result = GetOrAddInstance(serializationConfigurationType); return(result); }
private static void SeedAncestorsAndDescendants( SerializationConfigurationType serializationConfigurationType) { var serializationConfigurationConcreteType = serializationConfigurationType.ConcreteSerializationConfigurationDerivativeType; var assembliesToProcess = new HashSet <Assembly> { serializationConfigurationConcreteType.Assembly }; // The universe of types that we are interested in are scoped to the dependency tree of assemblies of the serialization // configuration type's assembly. The serialization configuration will depend on other serialization configuration // types and on domain types, which themselves will depend on other serialization configuration and domain types, and so on. assembliesToProcess.AddRange(GetRecursivelyReferencedAssemblies(serializationConfigurationConcreteType.Assembly)); // However, when the serialization configuration type is NOT in-subsystem, then there's the potential to miss some // assemblies. For example, lets say the consumer uses TypesToRegisterBsonSerializationConfiguration<T> and specifies // a T in their sub-system. TypesToRegisterBsonSerializationConfiguration<MyType> is in the OBC.Serialization.Bson assembly // and using the heuristic above, we won't traverse T's assembly. So this code recursively unpacks the generic arguments // (if any) of the serialization configuration type and adds the assemblies of those types to the list of assemblies to process. // One flaw with this approach is that the consumer could have created their own non-generic "wrapper" serialization configuration // in some assembly other than an assembly in the sub-system in question. For example, they could create a class // MyTypeToRegisterBsonSerializationConfiguration with a constructor that takes parameter of type Type. // So there's certainly an improvement that could be made to the code below that inspects all of the types referenced // by the serialization configuration type and not just the generic parameter types. assembliesToProcess.AddRange(GetRecursiveGenericArgumentAssemblies(serializationConfigurationConcreteType)); var typesToProcess = new List <Type>(); foreach (var assemblyToProcess in assembliesToProcess) { // add types in assemblies that we haven't processed yet if (!AssembliesThatHaveBeenProcessedForRelatedTypes.Contains(assemblyToProcess)) { var typesToConsiderForThisAssembly = new[] { assemblyToProcess } .GetTypesFromAssemblies() .Where(_ => !IsRestrictedType(_)) .ToList(); foreach (var typeToConsiderForThisAssembly in typesToConsiderForThisAssembly) { typesToProcess.Add(typeToConsiderForThisAssembly); } AssembliesThatHaveBeenProcessedForRelatedTypes.Add(assemblyToProcess); } } DiscoverAncestorsAndDescendants(typesToProcess); }
private static SerializationConfigurationBase GetOrAddInstance( SerializationConfigurationType serializationConfigurationType) { lock (SyncInstances) { if (!Instances.ContainsKey(serializationConfigurationType)) { var instance = serializationConfigurationType.ConcreteSerializationConfigurationDerivativeType.Construct <SerializationConfigurationBase>(); var children = instance.DependentSerializationConfigurationTypesWithDefaultsIfApplicable.Distinct().ToList(); var descendentTypeToInstanceMap = new Dictionary <SerializationConfigurationType, SerializationConfigurationBase>(); foreach (var child in children) { var childInstance = GetOrAddInstance(child); var childDescendantsTypeToInstanceMap = childInstance.DescendantSerializationConfigurationTypeToInstanceMap; // add the dependent's dependents to the dictionary foreach (var childDescendant in childDescendantsTypeToInstanceMap.Keys) { if (!descendentTypeToInstanceMap.ContainsKey(childDescendant)) { var childDescendantInstance = childDescendantsTypeToInstanceMap[childDescendant]; descendentTypeToInstanceMap.Add(childDescendant, childDescendantInstance); } } // add the dependent to the dictionary if (!descendentTypeToInstanceMap.ContainsKey(child)) { descendentTypeToInstanceMap.Add(child, childInstance); } } // initialize with fully resolve dependency tree instance.Initialize(descendentTypeToInstanceMap); Instances.Add(serializationConfigurationType, instance); } var result = Instances[serializationConfigurationType]; return(result); } }