Exemple #1
0
        /// <inheritdoc />
        protected override void RegisterTypes(IReadOnlyCollection <Type> types)
        {
            var registrationDetails = new RegistrationDetails(this.GetType());

            foreach (var type in types ?? new Type[0])
            {
                this.MutableRegisteredTypeToDetailsMap.Add(type, registrationDetails);
            }
        }
Exemple #2
0
        /// <summary>
        /// Run configuration logic.
        /// </summary>
        /// <param name="dependentConfigurationTypeToInstanceMap">Map of dependent configuration type to configured instance.</param>
        public virtual void Configure(IReadOnlyDictionary <Type, SerializationConfigurationBase> dependentConfigurationTypeToInstanceMap)
        {
            if (!this.configured)
            {
                lock (this.syncConfigure)
                {
                    if (!this.configured)
                    {
                        // Configure dependency map.
                        this.DependentConfigurationTypeToInstanceMap = dependentConfigurationTypeToInstanceMap;
                        foreach (var dependentConfigurationTypeToInstance in dependentConfigurationTypeToInstanceMap)
                        {
                            var dependentConfigType     = dependentConfigurationTypeToInstance.Key;
                            var dependentConfigInstance = dependentConfigurationTypeToInstance.Value;

                            var registrationDetails = new RegistrationDetails(dependentConfigType);

                            var dependentConfigRegisteredTypes = dependentConfigInstance
                                                                 .RegisteredTypeToDetailsMap
                                                                 .Where(_ => _.Value.RegisteringType == dependentConfigType).ToList();

                            foreach (var dependentConfigRegisteredType in dependentConfigRegisteredTypes)
                            {
                                this.MutableRegisteredTypeToDetailsMap.Add(
                                    dependentConfigRegisteredType.Key,
                                    registrationDetails);
                            }
                        }

                        // Save locals to work with.
                        var localClassTypesToRegister = this.ClassTypesToRegister ?? new List <Type>();
                        var localInterfaceTypesToRegisterImplementationOf = this.InterfaceTypesToRegisterImplementationOf ?? new List <Type>();
                        var localTypesToAutoRegisterWithDiscovery         = this.TypesToAutoRegisterWithDiscovery ?? new List <Type>();
                        var localTypesToAutoRegister = this.TypesToAutoRegister ?? new List <Type>();
                        var localClassTypesToRegisterAlongWithInheritors = this.ClassTypesToRegisterAlongWithInheritors ?? new List <Type>();

                        // Basic assertions.
                        this.DependentConfigurationTypeToInstanceMap.Must().NotBeNull();
                        localInterfaceTypesToRegisterImplementationOf.Must().NotContainAnyNullElements();
                        localTypesToAutoRegisterWithDiscovery.Must().NotContainAnyNullElements();
                        localTypesToAutoRegister.Must().NotContainAnyNullElements();
                        localClassTypesToRegisterAlongWithInheritors.Must().NotContainAnyNullElements();

                        localClassTypesToRegisterAlongWithInheritors.Select(_ => _.IsClass).Named(Invariant($"{nameof(this.ClassTypesToRegisterAlongWithInheritors)}.Select(_ => _.{nameof(Type.IsClass)})")).Must().Each().BeTrue();
                        localInterfaceTypesToRegisterImplementationOf.Select(_ => _.IsInterface).Named(Invariant($"{nameof(this.InterfaceTypesToRegisterImplementationOf)}.Select(_ => _.{nameof(Type.IsInterface)})")).Must().Each().BeTrue();

                        // Run optional initial config for the last inheritor.
                        this.InitialConfiguration();

                        // Run inheritor specific setup logic (like custom third party serializers/converters/resolvers).
                        this.InternalConfigure();

                        // Accumulate all possible types from configuration.
                        var discoveredTypes = this.DiscoverAllContainedAssignableTypes(localTypesToAutoRegisterWithDiscovery);

                        var typesToAutoRegister = new Type[0]
                                                  .Concat(localClassTypesToRegister)
                                                  .Concat(localTypesToAutoRegister)
                                                  .Concat(localInterfaceTypesToRegisterImplementationOf)
                                                  .Concat(localClassTypesToRegisterAlongWithInheritors)
                                                  .Concat(localTypesToAutoRegisterWithDiscovery)
                                                  .Concat(discoveredTypes)
                                                  .ToList();

                        var typesToAutoRegisterAlreadyHandledByDependentConfiguration = typesToAutoRegister.Intersect(this.RegisteredTypeToDetailsMap.Keys).ToList();
                        if (typesToAutoRegisterAlreadyHandledByDependentConfiguration.Any())
                        {
                            // TODO: what info do we want to capture here?
                            throw new DuplicateRegistrationException("Attempted to register types that are already registered", typesToAutoRegisterAlreadyHandledByDependentConfiguration);
                        }

                        var allTypesToRegister =
                            DiscoverAllAssignableTypes(typesToAutoRegister)
                            .Concat(discoveredTypes)
                            .Distinct()
                            .ToList();

                        // Register all types with inheritors to do additional configuration.
                        this.RegisterTypes(allTypesToRegister);

                        // Run optional final config for the last inheritor.
                        this.FinalConfiguration();

                        this.configured = true;
                    }
                }
            }
        }