protected override bool OnDeserializeUnrecognizedElement(string elementName, XmlReader reader)
        {
            switch (elementName)
            {
            case "add":
            {
                ServiceConfigurationElement service = new ServiceConfigurationElement();

                service.DeserializeElement(reader);

                this.BaseAdd(service);

                return(true);
            }

            case "remove":
            {
                RemoveServiceConfigurationElement service = new RemoveServiceConfigurationElement();

                service.DeserializeElement(reader);

                this.servicesToRemove.Add(service);

                return(true);
            }

            default:
                return(false);
            }
        }
        /// <inheritdoc />
        protected override object GetElementKey(ConfigurationElement element)
        {
            if (element is ServiceConfigurationElement)
            {
                ServiceConfigurationElement service = (ServiceConfigurationElement)element;

                return(string.Join("|", service.ContractType, service.ImplementationType, service.Key));
            }

            throw new NotSupportedException();
        }
        private void ValidateAndConvertValues(ServiceConfigurationElement serviceConfig)
        {
            this.ValidateCompositionConfiguration(serviceConfig);
            this.ValidateCollectionPropertyConfiguration(serviceConfig);

            if (serviceConfig.IsSelfRegistration)
            {
                return;
            }

            ConstructorInfo[] constructors = serviceConfig.ImplementationType.GetConstructors(BindingFlags.Instance | BindingFlags.Public)
                                             .Where(constructor => this.MatchConstructor(serviceConfig.ImplementationConstructorParameters, constructor))
                                             .ToArray();

            switch (constructors.Length)
            {
            case 0:
                throw new ConfigurationErrorsException(
                          "Matching implementation type '{0}' public constructor was not found.".FormatInvariant(serviceConfig.ImplementationType),
                          serviceConfig.ElementInformation.Source,
                          serviceConfig.ElementInformation.LineNumber);

            case 1:
                serviceConfig.ImplementationConstructorParameters.ResolvedConstructorInfo = constructors[0];
                break;

            default:
                throw new ConfigurationErrorsException(
                          "More than one matching public constructors of the implementation type '{0}' found. Please specify constructor parameters more explicitly.".FormatInvariant(serviceConfig.ImplementationType),
                          serviceConfig.ElementInformation.Source,
                          serviceConfig.ElementInformation.LineNumber);
            }

            Dictionary <string, Type> constructorParameters = serviceConfig.ImplementationConstructorParameters.ResolvedConstructorInfo.GetParameters().ToDictionary(p => p.Name, p => p.ParameterType);

            // Recalculate constructor parameter values because they are filled in MatchConstructor method.
            serviceConfig.ImplementationConstructorParameters
            .OfType <ConstructorValueConfigurationElement>()
            .ForEach(false, e => e.ConvertValue(constructorParameters[e.ParameterName]));
        }
        private void ValidateCompositionConfiguration(ServiceConfigurationElement serviceConfig)
        {
            serviceConfig.ValidateCompositionConfiguration();

            switch (serviceConfig.ImplementationComposition.Mode)
            {
            case CompositionMode.None:
            case CompositionMode.Empty:
            case CompositionMode.All:
                if ((serviceConfig.ImplementationComposition.ResolveKeys != null) && (serviceConfig.ImplementationComposition.ResolveKeys.Count > 0))
                {
                    throw new ConfigurationErrorsException(
                              "Implementation type '{0}' composition keys must be empty when mode is {1}.".FormatInvariant(serviceConfig.ImplementationType, serviceConfig.ImplementationComposition.Mode),
                              serviceConfig.ImplementationComposition.ElementInformation.Source,
                              serviceConfig.ImplementationComposition.ElementInformation.LineNumber);
                }

                break;

            case CompositionMode.Explicit:
                if (serviceConfig.ImplementationComposition.ResolveKeys != null)
                {
                    foreach (string resolveKey in serviceConfig.ImplementationComposition.ResolveKeys)
                    {
                        if (!this.CanResolve(serviceConfig.ContractType, resolveKey))
                        {
                            throw new ConfigurationErrorsException(
                                      "Implementation type '{0}' composition key '{0}' cannot be resolved.".FormatInvariant(serviceConfig.ImplementationType, resolveKey),
                                      serviceConfig.ImplementationComposition.ElementInformation.Source,
                                      serviceConfig.ImplementationComposition.ElementInformation.LineNumber);
                        }
                    }
                }

                break;

            default:
                throw new NotSupportedException <CompositionMode>(serviceConfig.ImplementationComposition.Mode);
            }
        }
        private void ValidateCollectionPropertyConfiguration(ServiceConfigurationElement serviceConfig)
        {
            foreach (CollectionPropertyConfigurationElement propertyConfig in serviceConfig.ImplementationProperties
                     .OfType <CollectionPropertyConfigurationElement>()
                     .Where(e => e.ResolveType == CollectionPropertyConfigurationElement.CollectionResolveType.Dependency))
            {
                propertyConfig.Validate(serviceConfig.ImplementationType);

                if (propertyConfig.ResolveKeys != null)
                {
                    foreach (string resolveKey in propertyConfig.ResolveKeys)
                    {
                        if (!this.CanResolve(propertyConfig.CollectionElementType, resolveKey))
                        {
                            throw new ConfigurationErrorsException(
                                      "Implementation type '{0}' property '{1}' resolve key '{2}' cannot be resolved.".FormatInvariant(serviceConfig.ImplementationType, propertyConfig.PropertyName, resolveKey),
                                      propertyConfig.ElementInformation.Source,
                                      propertyConfig.ElementInformation.LineNumber);
                        }
                    }
                }
            }
        }