/// <summary>
        /// Tries to get the part builder.
        /// </summary>
        /// <param name="serviceContractMetadata">The service contract metadata.</param>
        /// <param name="serviceContract">The service contract.</param>
        /// <param name="conventions">The conventions.</param>
        /// <param name="typeInfos">The type infos.</param>
        /// <returns>
        /// The part builder or <c>null</c>.
        /// </returns>
        private IPartConventionsBuilder TryGetPartBuilder(
            AppServiceContractAttribute serviceContractMetadata,
            TypeInfo serviceContract,
            IConventionsBuilder conventions,
            IEnumerable<TypeInfo> typeInfos)
        {
            var serviceContractType = serviceContract.AsType();

            if (serviceContract.IsGenericTypeDefinition)
            {
                // if there is non-generic service contract with the same full name
                // then add just the conventions for the derived types.
                return conventions.ForTypesMatching(t => this.MatchOpenGenericContractType(t, serviceContractType));
            }

            if (serviceContractMetadata.AllowMultiple)
            {
                // if the service contract metadata allows multiple service registrations
                // then add just the conventions for the derived types.
                return conventions.ForTypesDerivedFrom(serviceContractType);
            }

            var parts =
                typeInfos.Where(
                    ti =>
                    serviceContract.IsAssignableFrom(ti) && ti.IsClass && !ti.IsAbstract
                    && ti.GetCustomAttribute<ExcludeFromCompositionAttribute>() == null).ToList();
            if (parts.Count == 1)
            {
                return conventions.ForType(parts[0].AsType());
            }

            if (parts.Count > 1)
            {
                var overrideChain =
                    parts.ToDictionary(
                        ti => ti,
                        ti =>
                        ti.GetCustomAttribute<OverridePriorityAttribute>() ?? new OverridePriorityAttribute(Priority.Normal))
                        .OrderBy(item => item.Value.Value)
                        .ToList();

                var selectedPart = overrideChain[0].Key;
                if (overrideChain[0].Value.Value == overrideChain[1].Value.Value)
                {
                    throw new InvalidOperationException(
                        string.Format(
                            Strings.AmbiguousOverrideForAppServiceContract,
                            serviceContract,
                            selectedPart,
                            string.Join(", ", overrideChain.Select(item => item.Key.ToString() + ":" + item.Value.Value))));
                }

                return conventions.ForType(selectedPart.AsType());
            }

            return null;
        }
        /// <summary>
        /// Gets metadata attributes.
        /// </summary>
        /// <param name="contractAttribute">The contract attribute.</param>
        /// <returns>
        /// An array of type.
        /// </returns>
        private Type[] GetMetadataAttributes(AppServiceContractAttribute contractAttribute)
        {
            if (contractAttribute.MetadataAttributes == null || contractAttribute.MetadataAttributes.Length == 0)
            {
                return DefaultMetadataAttributes;
            }

            var attrs = contractAttribute.MetadataAttributes.ToList();
            foreach (var attr in DefaultMetadataAttributes)
            {
                if (!attrs.Contains(attr))
                {
                    attrs.Add(attr);
                }
            }

            return attrs.ToArray();
        }