Пример #1
0
        internal static ComposablePartDefinition GetMetadataViewProviderPartDefinition(Type providerType, int orderPrecedence, Resolver resolver)
        {
            Requires.NotNull(providerType, nameof(providerType));
            Requires.NotNull(resolver, nameof(resolver));

            var exportDefinition = new ExportDefinition(
                ContractNameServices.GetTypeIdentity(typeof(IMetadataViewProvider)),
                PartCreationPolicyConstraint.GetExportMetadata(CreationPolicy.Shared)
                .AddRange(ExportTypeIdentityConstraint.GetExportMetadata(typeof(IMetadataViewProvider)))
                .SetItem("OrderPrecedence", orderPrecedence));

            var partDefinition = new ComposablePartDefinition(
                TypeRef.Get(providerType, resolver),
                ImmutableDictionary <string, object> .Empty.Add(CompositionConstants.DgmlCategoryPartMetadataName, new[] { "VsMEFBuiltIn" }),
                new[] { exportDefinition },
                ImmutableDictionary <MemberRef, IReadOnlyCollection <ExportDefinition> > .Empty,
                ImmutableList <ImportDefinitionBinding> .Empty,
                string.Empty,
                default(MethodRef),
                MethodRef.Get(providerType.GetTypeInfo().GetConstructors(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance).Single(c => c.GetParameters().Length == 0), resolver),
                ImmutableList <ImportDefinitionBinding> .Empty,
                CreationPolicy.Shared,
                false);

            return(partDefinition);
        }
Пример #2
0
        private static RuntimeImport CreateRuntimeImport(ImportDefinitionBinding importDefinitionBinding, IReadOnlyList <ExportDefinitionBinding> satisfyingExports, Resolver resolver)
        {
            Requires.NotNull(importDefinitionBinding, nameof(importDefinitionBinding));
            Requires.NotNull(satisfyingExports, nameof(satisfyingExports));

            var runtimeExports = satisfyingExports.Select(export => CreateRuntimeExport(export, resolver)).ToImmutableArray();

            if (importDefinitionBinding.ImportingMemberRef != null)
            {
                return(new RuntimeImport(
                           importDefinitionBinding.ImportingMemberRef,
                           importDefinitionBinding.ImportingSiteTypeRef,
                           importDefinitionBinding.ImportingSiteTypeWithoutCollectionRef,
                           importDefinitionBinding.ImportDefinition.Cardinality,
                           runtimeExports,
                           PartCreationPolicyConstraint.IsNonSharedInstanceRequired(importDefinitionBinding.ImportDefinition),
                           importDefinitionBinding.IsExportFactory,
                           importDefinitionBinding.ImportDefinition.Metadata,
                           importDefinitionBinding.ImportDefinition.ExportFactorySharingBoundaries));
            }
            else
            {
                return(new RuntimeImport(
                           importDefinitionBinding.ImportingParameterRef,
                           importDefinitionBinding.ImportingSiteTypeRef,
                           importDefinitionBinding.ImportingSiteTypeWithoutCollectionRef,
                           importDefinitionBinding.ImportDefinition.Cardinality,
                           runtimeExports,
                           PartCreationPolicyConstraint.IsNonSharedInstanceRequired(importDefinitionBinding.ImportDefinition),
                           importDefinitionBinding.IsExportFactory,
                           importDefinitionBinding.ImportDefinition.Metadata,
                           importDefinitionBinding.ImportDefinition.ExportFactorySharingBoundaries));
            }
        }
            private protected override IEnumerable <ExportInfo> GetExportsCore(ImportDefinition importDefinition)
            {
                var exports = this.composition.GetExports(importDefinition.ContractName);

                return
                    (from export in exports
                     let part = this.composition.GetPart(export)
                                select this.CreateExport(
                         importDefinition,
                         export.Metadata,
                         part.TypeRef,
                         GetPartConstructedTypeRef(part, importDefinition.Metadata),
                         part.SharingBoundary,
                         !part.IsShared || PartCreationPolicyConstraint.IsNonSharedInstanceRequired(importDefinition),
                         export.MemberRef));
            }
Пример #4
0
            private IImportSatisfiabilityConstraint?ReadIImportSatisfiabilityConstraint()
            {
                using (this.Trace(nameof(IImportSatisfiabilityConstraint)))
                {
                    var type = (ConstraintTypes)this.reader !.ReadByte();
                    switch (type)
                    {
                    case ConstraintTypes.ImportMetadataViewConstraint:
                        uint count        = this.ReadCompressedUInt();
                        var  requirements = ImmutableDictionary.CreateBuilder <string, ImportMetadataViewConstraint.MetadatumRequirement>();
                        for (int i = 0; i < count; i++)
                        {
                            var name         = this.ReadString() !;
                            var valueTypeRef = this.ReadTypeRef() !;
                            var isRequired   = this.reader.ReadBoolean();
                            requirements.Add(name, new ImportMetadataViewConstraint.MetadatumRequirement(valueTypeRef, isRequired));
                        }

                        return(new ImportMetadataViewConstraint(requirements.ToImmutable(), this.Resolver));

                    case ConstraintTypes.ExportTypeIdentityConstraint:
                        string?exportTypeIdentity = this.ReadString() !;
                        return(new ExportTypeIdentityConstraint(exportTypeIdentity));

                    case ConstraintTypes.PartCreationPolicyConstraint:
                        CreationPolicy creationPolicy = this.ReadCreationPolicy();
                        return(PartCreationPolicyConstraint.GetRequiredCreationPolicyConstraint(creationPolicy));

                    case ConstraintTypes.ExportMetadataValueImportConstraint:
                    {
                        string?name  = this.ReadString() !;
                        object?value = this.ReadObject();
                        return(new ExportMetadataValueImportConstraint(name, value));
                    }

                    default:
                        throw new NotSupportedException(string.Format(CultureInfo.CurrentCulture, Strings.UnexpectedConstraintType, type));
                    }
                }
            }
Пример #5
0
            private static ImportDefinition WrapImportDefinition(MefV1.Primitives.ImportDefinition definition)
            {
                Requires.NotNull(definition, nameof(definition));

                var contractImportDefinition = definition as MefV1.Primitives.ContractBasedImportDefinition;

                var constraints = ImmutableHashSet <IImportSatisfiabilityConstraint> .Empty
                                  .Add(new ImportConstraint(definition));

                if (contractImportDefinition != null)
                {
                    constraints = constraints.Union(PartCreationPolicyConstraint.GetRequiredCreationPolicyConstraints(WrapCreationPolicy(contractImportDefinition.RequiredCreationPolicy)));
                }

                // Do NOT propagate the cardinality otherwise the export provider will throw
                // if the cardinality is not met. But it's not our job to throw, since the caller
                // is going to aggregate our response with other export providers and finally
                // be responsible for throwing if the ultimate receiver of the result doesn't
                // get what they expect.
                // We use ZeroOrMore to indicate we'll accept any response.
                var cardinality = ImportCardinality.ZeroOrMore;

                var metadata = (IReadOnlyDictionary <string, object>)definition.Metadata;

                MefV1.Primitives.ImportDefinition productImportDefinitionV1 = GetExportFactoryProductImportDefinitionIfApplicable(definition);

                if (productImportDefinitionV1 != null)
                {
                    var productImportDefinitionV3 = WrapImportDefinition(productImportDefinitionV1);
                    metadata = metadata.ToImmutableDictionary()
                               .Add(CompositionConstants.ExportFactoryProductImportDefinition, productImportDefinitionV3)
                               .Add(CompositionConstants.ExportFactoryTypeMetadataName, ExportFactoryV1Type);
                }

                return(new ImportDefinition(definition.ContractName, cardinality, metadata, constraints));
            }
Пример #6
0
        private static IEnumerable <ComposedPartDiagnostic> FindLoops(IEnumerable <ComposedPart> parts)
        {
            Requires.NotNull(parts, nameof(parts));

            var partByPartDefinition  = parts.ToDictionary(p => p.Definition);
            var partByPartType        = parts.ToDictionary(p => p.Definition.TypeRef);
            var partsAndDirectImports = new Dictionary <ComposedPart, IReadOnlyList <KeyValuePair <ImportDefinitionBinding, ComposedPart> > >();

            foreach (var part in parts)
            {
                var directlyImportedParts = (from importAndExports in part.SatisfyingExports
                                             from export in importAndExports.Value
                                             let exportingPart = partByPartDefinition[export.PartDefinition]
                                                                 select new KeyValuePair <ImportDefinitionBinding, ComposedPart>(importAndExports.Key, exportingPart)).ToList();
                partsAndDirectImports.Add(part, directlyImportedParts);
            }

            Func <Func <KeyValuePair <ImportDefinitionBinding, ComposedPart>, bool>, Func <ComposedPart, IEnumerable <ComposedPart> > > getDirectLinksWithFilter =
                filter => (part => partsAndDirectImports[part].Where(filter).Select(ip => ip.Value));
            var visited = new HashSet <ComposedPart>();

            // Find any loops of exclusively non-shared parts.
            var nonSharedPartsInLoops = new HashSet <ComposedPart>();

            foreach (var part in partsAndDirectImports.Keys)
            {
                if (nonSharedPartsInLoops.Contains(part))
                {
                    // Don't check and report parts already detected to be involved in a loop.
                    continue;
                }

                visited.Clear();
                var path = PathExistsBetween(part, part, getDirectLinksWithFilter(ip => !ip.Key.IsExportFactory && (!ip.Value.Definition.IsShared || PartCreationPolicyConstraint.IsNonSharedInstanceRequired(ip.Key.ImportDefinition))), visited);
                if (!path.IsEmpty)
                {
                    path = path.Push(part);
                    nonSharedPartsInLoops.UnionWith(path);
                    yield return(new ComposedPartDiagnostic(path, Strings.LoopBetweenNonSharedParts));
                }
            }

            // Find loops even with shared parts where an importing constructor is involved.
            Func <KeyValuePair <ImportDefinitionBinding, ComposedPart>, bool> importingConstructorFilter = ip => !ip.Key.IsExportFactory && !ip.Key.IsLazy;

            foreach (var partAndImports in partsAndDirectImports)
            {
                var importingPart = partAndImports.Key;
                foreach (var import in partAndImports.Value)
                {
                    var importDefinitionBinding = import.Key;
                    var satisfyingPart          = import.Value;
                    if (importDefinitionBinding.ImportingParameterRef != null && importingConstructorFilter(import))
                    {
                        visited.Clear();
                        var path = PathExistsBetween(satisfyingPart, importingPart, getDirectLinksWithFilter(importingConstructorFilter), visited);
                        if (!path.IsEmpty)
                        {
                            path = path.Push(satisfyingPart).Push(partByPartType[importDefinitionBinding.ComposablePartTypeRef]);
                            yield return(new ComposedPartDiagnostic(path, Strings.LoopInvolvingImportingCtorArgumentAndAllNonLazyImports));
                        }
                    }
                }
            }
        }
Пример #7
0
        protected override ComposablePartDefinition?CreatePart(Type partType, bool typeExplicitlyRequested)
        {
            Requires.NotNull(partType, nameof(partType));

            var partTypeInfo = partType.GetTypeInfo();

            if (!typeExplicitlyRequested)
            {
                bool isPublic = partType.IsNested ? partTypeInfo.IsNestedPublic : partTypeInfo.IsPublic;
                if (!this.IsNonPublicSupported && !isPublic)
                {
                    // Skip non-public types.
                    return(null);
                }
            }

            var declaredProperties  = partTypeInfo.GetProperties(BindingFlags.Instance | this.PublicVsNonPublicFlags);
            var exportingProperties = from member in declaredProperties
                                      from export in member.GetAttributes <ExportAttribute>()
                                      where member.GetMethod != null // MEFv2 quietly omits exporting properties with no getter
                                      select new KeyValuePair <MemberInfo, ExportAttribute>(member, export);
            var exportedTypes = from export in partTypeInfo.GetAttributes <ExportAttribute>()
                                select new KeyValuePair <MemberInfo, ExportAttribute>(partTypeInfo, export);
            var exportsByMember = (from export in exportingProperties.Concat(exportedTypes)
                                   group export.Value by export.Key into exportsByType
                                   select exportsByType).Select(g => new KeyValuePair <MemberInfo, ExportAttribute[]>(g.Key, g.ToArray())).ToArray();

            if (exportsByMember.Length == 0)
            {
                return(null);
            }

            // Check for PartNotDiscoverable only after we've established it's an interesting part.
            // This optimizes for the fact that most types have no exports, in which case it's not a discoverable
            // part anyway. Checking for the PartNotDiscoverableAttribute first, which is rarely defined,
            // doesn't usually pay for itself in terms of short-circuiting. But it does add an extra
            // attribute to look for that we don't need to find for all the types that have no export attributes either.
            if (!typeExplicitlyRequested && partTypeInfo.IsAttributeDefined <PartNotDiscoverableAttribute>())
            {
                return(null);
            }

            foreach (var exportingMember in exportsByMember)
            {
                this.ThrowOnInvalidExportingMember(exportingMember.Key);
            }

            TypeRef partTypeRef = TypeRef.Get(partType, this.Resolver);
            Type?   partTypeAsGenericTypeDefinition = partTypeInfo.IsGenericType ? partType.GetGenericTypeDefinition() : null;

            string?sharingBoundary = null;
            var    sharedAttribute = partTypeInfo.GetFirstAttribute <SharedAttribute>();

            if (sharedAttribute != null)
            {
                sharingBoundary = sharedAttribute.SharingBoundary ?? string.Empty;
            }

            CreationPolicy partCreationPolicy = sharingBoundary != null ? CreationPolicy.Shared : CreationPolicy.NonShared;
            var            allExportsMetadata = ImmutableDictionary.CreateRange(PartCreationPolicyConstraint.GetExportMetadata(partCreationPolicy));

            var exportsOnType    = ImmutableList.CreateBuilder <ExportDefinition>();
            var exportsOnMembers = ImmutableDictionary.CreateBuilder <MemberRef, IReadOnlyCollection <ExportDefinition> >();
            var imports          = ImmutableList.CreateBuilder <ImportDefinitionBinding>();

            foreach (var export in exportsByMember)
            {
                var member = export.Key;
                var memberExportMetadata = allExportsMetadata.AddRange(this.GetExportMetadata(member));

                if (member is TypeInfo)
                {
                    foreach (var exportAttribute in export.Value)
                    {
                        Type             exportedType     = exportAttribute.ContractType ?? partTypeAsGenericTypeDefinition ?? partType;
                        ExportDefinition exportDefinition = CreateExportDefinition(memberExportMetadata, exportAttribute, exportedType);
                        exportsOnType.Add(exportDefinition);
                    }
                }
                else // property
                {
                    var property = (PropertyInfo)member;
                    Verify.Operation(!partTypeInfo.IsGenericTypeDefinition, Strings.ExportsOnMembersNotAllowedWhenDeclaringTypeGeneric);
                    var exportDefinitions = ImmutableList.CreateBuilder <ExportDefinition>();
                    foreach (var exportAttribute in export.Value)
                    {
                        Type             exportedType     = exportAttribute.ContractType ?? property.PropertyType;
                        ExportDefinition exportDefinition = CreateExportDefinition(memberExportMetadata, exportAttribute, exportedType);
                        exportDefinitions.Add(exportDefinition);
                    }

                    exportsOnMembers.Add(MemberRef.Get(member, this.Resolver), exportDefinitions.ToImmutable());
                }
            }

            foreach (var member in declaredProperties)
            {
                var importAttribute     = member.GetFirstAttribute <ImportAttribute>();
                var importManyAttribute = member.GetFirstAttribute <ImportManyAttribute>();
                Requires.Argument(!(importAttribute != null && importManyAttribute != null), "partType", Strings.MemberContainsBothImportAndImportMany, member.Name);

                var importConstraints = GetImportConstraints(member);
                ImportDefinition?importDefinition;
                if (this.TryCreateImportDefinition(ReflectionHelpers.GetMemberType(member), member, importConstraints, out importDefinition))
                {
                    var importDefinitionBinding = new ImportDefinitionBinding(
                        importDefinition,
                        TypeRef.Get(partType, this.Resolver),
                        MemberRef.Get(member, this.Resolver),
                        TypeRef.Get(member.PropertyType, this.Resolver),
                        TypeRef.Get(GetImportingSiteTypeWithoutCollection(importDefinition, member.PropertyType), this.Resolver));
                    imports.Add(importDefinitionBinding);
                }
            }

            MethodInfo?onImportsSatisfied = null;

            foreach (var method in partTypeInfo.GetMethods(this.PublicVsNonPublicFlags | BindingFlags.Instance))
            {
                if (method.IsAttributeDefined <OnImportsSatisfiedAttribute>())
                {
                    Verify.Operation(method.GetParameters().Length == 0, Strings.OnImportsSatisfiedTakeNoParameters);
                    Verify.Operation(onImportsSatisfied == null, Strings.OnlyOneOnImportsSatisfiedMethodIsSupported);
                    onImportsSatisfied = method;
                }
            }

            var importingConstructorParameters = ImmutableList.CreateBuilder <ImportDefinitionBinding>();
            var importingCtor = GetImportingConstructor <ImportingConstructorAttribute>(partType, publicOnly: !this.IsNonPublicSupported);

            Verify.Operation(importingCtor != null, Strings.NoImportingConstructorFound);
            foreach (var parameter in importingCtor.GetParameters())
            {
                var import = this.CreateImport(parameter, GetImportConstraints(parameter));
                if (import.ImportDefinition.Cardinality == ImportCardinality.ZeroOrMore)
                {
                    Verify.Operation(PartDiscovery.IsImportManyCollectionTypeCreateable(import), Strings.CollectionMustBePublicAndPublicCtorWhenUsingImportingCtor);
                }

                importingConstructorParameters.Add(import);
            }

            var partMetadata = ImmutableDictionary.CreateBuilder <string, object?>();

            foreach (var partMetadataAttribute in partTypeInfo.GetAttributes <PartMetadataAttribute>())
            {
                partMetadata[partMetadataAttribute.Name] = partMetadataAttribute.Value;
            }

            var assemblyNamesForMetadataAttributes = ImmutableHashSet.CreateBuilder <AssemblyName>(ByValueEquality.AssemblyName);

            foreach (var export in exportsByMember)
            {
                GetAssemblyNamesFromMetadataAttributes <MetadataAttributeAttribute>(export.Key, assemblyNamesForMetadataAttributes);
            }

            return(new ComposablePartDefinition(
                       TypeRef.Get(partType, this.Resolver),
                       partMetadata.ToImmutable(),
                       exportsOnType.ToImmutable(),
                       exportsOnMembers.ToImmutable(),
                       imports.ToImmutable(),
                       sharingBoundary,
                       MethodRef.Get(onImportsSatisfied, this.Resolver),
                       MethodRef.Get(importingCtor, this.Resolver),
                       importingConstructorParameters.ToImmutable(),
                       partCreationPolicy,
                       assemblyNamesForMetadataAttributes));
        }
Пример #8
0
        private bool TryCreateImportDefinition(Type importingType, ICustomAttributeProvider member, [NotNullWhen(true)] out ImportDefinition?importDefinition)
        {
            Requires.NotNull(importingType, nameof(importingType));
            Requires.NotNull(member, nameof(member));

            ImportAttribute     importAttribute     = member.GetFirstAttribute <ImportAttribute>();
            ImportManyAttribute importManyAttribute = member.GetFirstAttribute <ImportManyAttribute>();

            // Importing constructors get implied attributes on their parameters.
            if (importAttribute == null && importManyAttribute == null && member is ParameterInfo)
            {
                importAttribute = new ImportAttribute();
            }

            if (importAttribute != null)
            {
                this.ThrowOnInvalidImportingMemberOrParameter(member, isImportMany: false);

                if (importAttribute.Source != ImportSource.Any)
                {
                    throw new NotSupportedException(Strings.CustomImportSourceNotSupported);
                }

                var requiredCreationPolicy = importingType.IsExportFactoryTypeV1()
                    ? CreationPolicy.NonShared
                    : (CreationPolicy)importAttribute.RequiredCreationPolicy;

                Type contractType = importAttribute.ContractType ?? GetTypeIdentityFromImportingType(importingType, importMany: false);
                var  constraints  = PartCreationPolicyConstraint.GetRequiredCreationPolicyConstraints(requiredCreationPolicy)
                                    .Union(this.GetMetadataViewConstraints(importingType, importMany: false))
                                    .Union(GetExportTypeIdentityConstraints(contractType));
                importDefinition = new ImportDefinition(
                    string.IsNullOrEmpty(importAttribute.ContractName) ? GetContractName(contractType) : importAttribute.ContractName,
                    importAttribute.AllowDefault ? ImportCardinality.OneOrZero : ImportCardinality.ExactlyOne,
                    GetImportMetadataForGenericTypeImport(contractType),
                    constraints);
                return(true);
            }
            else if (importManyAttribute != null)
            {
                this.ThrowOnInvalidImportingMemberOrParameter(member, isImportMany: true);

                if (importManyAttribute.Source != ImportSource.Any)
                {
                    throw new NotSupportedException(Strings.CustomImportSourceNotSupported);
                }

                var requiredCreationPolicy = GetElementTypeFromMany(importingType).IsExportFactoryTypeV1()
                    ? CreationPolicy.NonShared
                    : (CreationPolicy)importManyAttribute.RequiredCreationPolicy;

                Type contractType = importManyAttribute.ContractType ?? GetTypeIdentityFromImportingType(importingType, importMany: true);
                var  constraints  = PartCreationPolicyConstraint.GetRequiredCreationPolicyConstraints(requiredCreationPolicy)
                                    .Union(this.GetMetadataViewConstraints(importingType, importMany: true))
                                    .Union(GetExportTypeIdentityConstraints(contractType));
                importDefinition = new ImportDefinition(
                    string.IsNullOrEmpty(importManyAttribute.ContractName) ? GetContractName(contractType) : importManyAttribute.ContractName,
                    ImportCardinality.ZeroOrMore,
                    GetImportMetadataForGenericTypeImport(contractType),
                    constraints);
                return(true);
            }
            else
            {
                importDefinition = null;
                return(false);
            }
        }
Пример #9
0
        protected override ComposablePartDefinition?CreatePart(Type partType, bool typeExplicitlyRequested)
        {
            Requires.NotNull(partType, nameof(partType));

            var partTypeInfo = partType.GetTypeInfo();

            // We want to ignore abstract classes, but we want to consider static classes.
            // Static classes claim to be both abstract and sealed. So to ignore just abstract
            // ones, we check that they are not sealed.
            if (partTypeInfo.IsAbstract && !partTypeInfo.IsSealed)
            {
                return(null);
            }

            BindingFlags everythingLocal = BindingFlags.DeclaredOnly | BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic;
            BindingFlags instanceLocal   = BindingFlags.DeclaredOnly | BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic;

            // If the type is abstract only find local static exports
            var exportBindingFlags = everythingLocal;

            if (partTypeInfo.IsAbstract)
            {
                exportBindingFlags &= ~BindingFlags.Instance;
            }

            var declaredMethods    = partType.GetMethods(exportBindingFlags); // methods can only export, not import
            var declaredProperties = partType.GetProperties(everythingLocal);
            var declaredFields     = partType.GetFields(everythingLocal);

            var allLocalMembers  = declaredMethods.Concat <MemberInfo>(declaredProperties).Concat(declaredFields);
            var exportingMembers = from member in allLocalMembers
                                   from export in member.GetAttributes <ExportAttribute>()
                                   select new KeyValuePair <MemberInfo, ExportAttribute>(member, export);
            var exportedTypes = from export in partTypeInfo.GetAttributes <ExportAttribute>()
                                select new KeyValuePair <MemberInfo, ExportAttribute>(partTypeInfo, export);
            var inheritedExportedTypes = from baseTypeOrInterface in partType.GetInterfaces().Concat(partType.EnumTypeAndBaseTypes().Skip(1))
                                         where baseTypeOrInterface != typeof(object)
                                         from export in baseTypeOrInterface.GetTypeInfo().GetAttributes <InheritedExportAttribute>()
                                         select new KeyValuePair <MemberInfo, ExportAttribute>(baseTypeOrInterface.GetTypeInfo(), export);

            var exportsByMember = (from export in exportingMembers.Concat(exportedTypes).Concat(inheritedExportedTypes)
                                   group export.Value by export.Key into exportsByType
                                   select exportsByType).Select(g => new KeyValuePair <MemberInfo, ExportAttribute[]>(g.Key, g.ToArray())).ToArray();

            if (exportsByMember.Length == 0)
            {
                return(null);
            }

            // Check for PartNotDiscoverable only after we've established it's an interesting part.
            // This optimizes for the fact that most types have no exports, in which case it's not a discoverable
            // part anyway. Checking for the PartNotDiscoverableAttribute first, which is rarely defined,
            // doesn't usually pay for itself in terms of short-circuiting. But it does add an extra
            // attribute to look for that we don't need to find for all the types that have no export attributes either.
            if (!typeExplicitlyRequested && partTypeInfo.IsAttributeDefined <PartNotDiscoverableAttribute>())
            {
                return(null);
            }

            foreach (var exportingMember in exportsByMember)
            {
                this.ThrowOnInvalidExportingMember(exportingMember.Key);
            }

            TypeRef partTypeRef = TypeRef.Get(partType, this.Resolver);
            Type?   partTypeAsGenericTypeDefinition = partTypeInfo.IsGenericType ? partType.GetGenericTypeDefinition() : null;

            // Collect information for all imports.
            var imports = ImmutableList.CreateBuilder <ImportDefinitionBinding>();

            this.AddImportsFromMembers(declaredProperties, declaredFields, partTypeRef, imports);
            Type?baseType = partTypeInfo.BaseType;

            while (baseType != null && baseType != typeof(object))
            {
                this.AddImportsFromMembers(baseType.GetProperties(instanceLocal), baseType.GetFields(instanceLocal), partTypeRef, imports);
                baseType = baseType.GetTypeInfo().BaseType;
            }

            var partCreationPolicy          = CreationPolicy.Any;
            var partCreationPolicyAttribute = partTypeInfo.GetFirstAttribute <PartCreationPolicyAttribute>();

            if (partCreationPolicyAttribute != null)
            {
                partCreationPolicy = (CreationPolicy)partCreationPolicyAttribute.CreationPolicy;
            }

            var allExportsMetadata = ImmutableDictionary.CreateRange(PartCreationPolicyConstraint.GetExportMetadata(partCreationPolicy));
            var inheritedExportContractNamesFromNonInterfaces = ImmutableHashSet.CreateBuilder <string>();
            var exportDefinitions = ImmutableList.CreateBuilder <KeyValuePair <MemberInfo, ExportDefinition> >();

            foreach (var export in exportsByMember)
            {
                var memberExportMetadata = allExportsMetadata.AddRange(GetExportMetadata(export.Key));

                if (export.Key is MethodInfo method)
                {
                    var exportAttributes = export.Value;
                    if (exportAttributes.Any())
                    {
                        foreach (var exportAttribute in exportAttributes)
                        {
                            Type   exportedType   = exportAttribute.ContractType ?? ReflectionHelpers.GetContractTypeForDelegate(method);
                            string contractName   = string.IsNullOrEmpty(exportAttribute.ContractName) ? GetContractName(exportedType) : exportAttribute.ContractName;
                            var    exportMetadata = memberExportMetadata
                                                    .Add(CompositionConstants.ExportTypeIdentityMetadataName, ContractNameServices.GetTypeIdentity(exportedType));
                            var exportDefinition = new ExportDefinition(contractName, exportMetadata);
                            exportDefinitions.Add(new KeyValuePair <MemberInfo, ExportDefinition>(export.Key, exportDefinition));
                        }
                    }
                }
                else
                {
                    MemberInfo exportingTypeOrPropertyOrField = export.Key;
                    Verify.Operation(export.Key is TypeInfo || !partTypeInfo.IsGenericTypeDefinition, Strings.ExportsOnMembersNotAllowedWhenDeclaringTypeGeneric);
                    Type exportSiteType = ReflectionHelpers.GetMemberType(exportingTypeOrPropertyOrField);
                    foreach (var exportAttribute in export.Value)
                    {
                        Type   exportedType = exportAttribute.ContractType ?? partTypeAsGenericTypeDefinition ?? exportSiteType;
                        string contractName = string.IsNullOrEmpty(exportAttribute.ContractName) ? GetContractName(exportedType) : exportAttribute.ContractName;
                        if (export.Key is TypeInfo && exportAttribute is InheritedExportAttribute)
                        {
                            if (inheritedExportContractNamesFromNonInterfaces.Contains(contractName))
                            {
                                // We already have an export with this contract name on this type (from a more derived type)
                                // using InheritedExportAttribute.
                                continue;
                            }

                            if (!((TypeInfo)export.Key).IsInterface)
                            {
                                inheritedExportContractNamesFromNonInterfaces.Add(contractName);
                            }
                        }

                        var exportMetadata = memberExportMetadata
                                             .Add(CompositionConstants.ExportTypeIdentityMetadataName, ContractNameServices.GetTypeIdentity(exportedType));
                        var exportDefinition = new ExportDefinition(contractName, exportMetadata);
                        exportDefinitions.Add(new KeyValuePair <MemberInfo, ExportDefinition>(export.Key, exportDefinition));
                    }
                }
            }

            MethodInfo?onImportsSatisfied = null;

            if (typeof(IPartImportsSatisfiedNotification).IsAssignableFrom(partType))
            {
                onImportsSatisfied = OnImportsSatisfiedMethodInfo;
            }

            var importingConstructorParameters = ImmutableList.CreateBuilder <ImportDefinitionBinding>();
            var importingCtor = GetImportingConstructor <ImportingConstructorAttribute>(partType, publicOnly: false);

            if (importingCtor != null) // some parts have exports merely for metadata -- they can't be instantiated
            {
                foreach (var parameter in importingCtor.GetParameters())
                {
                    var import = this.CreateImport(parameter);
                    if (import.ImportDefinition.Cardinality == ImportCardinality.ZeroOrMore)
                    {
                        Verify.Operation(PartDiscovery.IsImportManyCollectionTypeCreateable(import), Strings.CollectionMustBePublicAndPublicCtorWhenUsingImportingCtor);
                    }

                    importingConstructorParameters.Add(import);
                }
            }

            var partMetadata = ImmutableDictionary.CreateBuilder <string, object?>();

            foreach (var partMetadataAttribute in partTypeInfo.GetAttributes <PartMetadataAttribute>())
            {
                partMetadata[partMetadataAttribute.Name] = partMetadataAttribute.Value;
            }

            var exportsOnType    = exportDefinitions.Where(kv => kv.Key is TypeInfo).Select(kv => kv.Value).ToArray();
            var exportsOnMembers = (from kv in exportDefinitions
                                    where !(kv.Key is TypeInfo)
                                    group kv.Value by kv.Key into byMember
                                    select byMember).ToDictionary(g => MemberRef.Get(g.Key, this.Resolver), g => (IReadOnlyCollection <ExportDefinition>)g.ToArray());

            var assemblyNamesForMetadataAttributes = ImmutableHashSet.CreateBuilder <AssemblyName>(ByValueEquality.AssemblyName);

            foreach (var export in exportsByMember)
            {
                GetAssemblyNamesFromMetadataAttributes <MetadataAttributeAttribute>(export.Key, assemblyNamesForMetadataAttributes);
            }

            return(new ComposablePartDefinition(
                       TypeRef.Get(partType, this.Resolver),
                       partMetadata.ToImmutable(),
                       exportsOnType,
                       exportsOnMembers,
                       imports.ToImmutable(),
                       partCreationPolicy != CreationPolicy.NonShared ? string.Empty : null,
                       MethodRef.Get(onImportsSatisfied, this.Resolver),
                       MethodRef.Get(importingCtor, this.Resolver),
                       importingCtor != null ? importingConstructorParameters.ToImmutable() : null, // some MEF parts are only for metadata
                       partCreationPolicy,
                       assemblyNamesForMetadataAttributes,
                       partCreationPolicy != CreationPolicy.NonShared));
        }