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); }
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)); }
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)); } } }
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)); }
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)); } } } } }
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)); }
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); } }
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)); }