private RuntimeComposition.RuntimePart ReadRuntimePart() { using (this.Trace("RuntimePart")) { ConstructorRef importingCtor = default(ConstructorRef); IReadOnlyList <RuntimeComposition.RuntimeImport> importingCtorArguments = ImmutableList <RuntimeComposition.RuntimeImport> .Empty; var type = this.ReadTypeRef(); var exports = this.ReadList(this.reader, this.ReadRuntimeExport); bool hasCtor = this.reader.ReadBoolean(); if (hasCtor) { importingCtor = this.ReadConstructorRef(); importingCtorArguments = this.ReadList(this.reader, this.ReadRuntimeImport); } var importingMembers = this.ReadList(this.reader, this.ReadRuntimeImport); var onImportsSatisfied = this.ReadMethodRef(); var sharingBoundary = this.ReadString(); return(new RuntimeComposition.RuntimePart( type, importingCtor, importingCtorArguments, importingMembers, exports, onImportsSatisfied, sharingBoundary)); } }
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), ConstructorRef.Get(providerType.GetConstructor(System.Reflection.BindingFlags.Public | System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance, null, new Type[0], null), resolver), ImmutableList <ImportDefinitionBinding> .Empty, CreationPolicy.Shared, false); return(partDefinition); }
protected void Write(ConstructorRef constructorRef) { Requires.Argument(!constructorRef.IsEmpty, "constructorRef", Strings.CannotBeEmpty); using (this.Trace("ConstructorRef")) { this.Write(constructorRef.DeclaringType); this.WriteCompressedMetadataToken(constructorRef.MetadataToken, MetadataTokenType.Method); } }
private ConstructorRef Scramble(ConstructorRef constructorRef) { if (constructorRef.IsEmpty) { return(default(ConstructorRef)); } return(new ConstructorRef( this.Scramble(constructorRef.DeclaringType), this.GetScrambledMetadataToken(constructorRef.MetadataToken), constructorRef.ParameterTypes.Select(this.Scramble).ToImmutableArray())); }
public RuntimePart( TypeRef type, ConstructorRef importingConstructor, IReadOnlyList <RuntimeImport> importingConstructorArguments, IReadOnlyList <RuntimeImport> importingMembers, IReadOnlyList <RuntimeExport> exports, MethodRef onImportsSatisfied, string sharingBoundary) { this.TypeRef = type; this.ImportingConstructorRef = importingConstructor; this.ImportingConstructorArguments = importingConstructorArguments; this.ImportingMembers = importingMembers; this.Exports = exports; this.OnImportsSatisfiedRef = onImportsSatisfied; this.SharingBoundary = sharingBoundary; }
private ComposablePartDefinition ReadComposablePartDefinition() { using (this.Trace("ComposablePartDefinition")) { var partType = this.ReadTypeRef(); var partMetadata = this.ReadMetadata(); var exportedTypes = this.ReadList(this.ReadExportDefinition); var exportingMembers = ImmutableDictionary.CreateBuilder <MemberRef, IReadOnlyCollection <ExportDefinition> >(); uint exportedMembersCount = this.ReadCompressedUInt(); for (int i = 0; i < exportedMembersCount; i++) { var member = this.ReadMemberRef(); var exports = this.ReadList(this.ReadExportDefinition); exportingMembers.Add(member, exports); } var importingMembers = this.ReadList(this.ReadImportDefinitionBinding); var sharingBoundary = this.ReadString(); var onImportsSatisfied = this.ReadMethodRef(); ConstructorRef importingConstructor = default(ConstructorRef); IReadOnlyList <ImportDefinitionBinding> importingConstructorImports = null; if (this.reader.ReadBoolean()) { importingConstructor = this.ReadConstructorRef(); importingConstructorImports = this.ReadList(this.ReadImportDefinitionBinding); } var creationPolicy = this.ReadCreationPolicy(); var isSharingBoundaryInferred = this.reader.ReadBoolean(); var part = new ComposablePartDefinition( partType, partMetadata, exportedTypes, exportingMembers, importingMembers, sharingBoundary, onImportsSatisfied, importingConstructor, importingConstructorImports, creationPolicy, isSharingBoundaryInferred); return(part); } }
public RuntimePart( TypeRef type, ConstructorRef importingConstructor, IReadOnlyList <RuntimeImport> importingConstructorArguments, IReadOnlyList <RuntimeImport> importingMembers, IReadOnlyList <RuntimeExport> exports, MethodRef onImportsSatisfied, string sharingBoundary) : this( type, new MethodRef(importingConstructor), importingConstructorArguments, importingMembers, exports, onImportsSatisfied, sharingBoundary) { }
public ComposablePartDefinition(TypeRef partType, IReadOnlyDictionary <string, object> metadata, IReadOnlyCollection <ExportDefinition> exportedTypes, IReadOnlyDictionary <MemberRef, IReadOnlyCollection <ExportDefinition> > exportingMembers, IEnumerable <ImportDefinitionBinding> importingMembers, string sharingBoundary, MethodRef onImportsSatisfied, ConstructorRef importingConstructorRef, IReadOnlyList <ImportDefinitionBinding> importingConstructorImports, CreationPolicy partCreationPolicy, IEnumerable <AssemblyName> extraInputAssemblies, bool isSharingBoundaryInferred = false) : this( partType, metadata, exportedTypes, exportingMembers, importingMembers, sharingBoundary, onImportsSatisfied, new MethodRef(importingConstructorRef), importingConstructorImports, partCreationPolicy, extraInputAssemblies, isSharingBoundaryInferred) { }
protected override ComposablePartDefinition CreatePart(Type partType, bool typeExplicitlyRequested) { Requires.NotNull(partType, nameof(partType)); if (!typeExplicitlyRequested) { bool isPublic = partType.IsNested ? partType.IsNestedPublic : partType.IsPublic; if (!this.IsNonPublicSupported && !isPublic) { // Skip non-public types. return(null); } } var declaredProperties = partType.GetProperties(BindingFlags.Instance | this.PublicVsNonPublicFlags); var exportingProperties = from member in declaredProperties from export in member.GetAttributes <ExportAttribute>() select new KeyValuePair <MemberInfo, ExportAttribute>(member, export); var exportedTypes = from export in partType.GetAttributes <ExportAttribute>() select new KeyValuePair <MemberInfo, ExportAttribute>(partType, 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 && partType.IsAttributeDefined <PartNotDiscoverableAttribute>()) { return(null); } TypeRef partTypeRef = TypeRef.Get(partType, this.Resolver); Type partTypeAsGenericTypeDefinition = partType.IsGenericType ? partType.GetGenericTypeDefinition() : null; string sharingBoundary = null; var sharedAttribute = partType.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 Type) { 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(!partType.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)) { imports.Add(new ImportDefinitionBinding(importDefinition, TypeRef.Get(partType, this.Resolver), MemberRef.Get(member, this.Resolver))); } } MethodInfo onImportsSatisfied = null; foreach (var method in partType.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 partType.GetAttributes <PartMetadataAttribute>()) { partMetadata[partMetadataAttribute.Name] = partMetadataAttribute.Value; } var assemblyNamesForMetadataAttributes = ImmutableHashSet.CreateBuilder <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), ConstructorRef.Get(importingCtor, this.Resolver), importingConstructorParameters.ToImmutable(), partCreationPolicy, assemblyNamesForMetadataAttributes)); }
/// <summary> /// Initializes a new instance of the <see cref="ComposablePartDefinition"/> class. /// </summary> /// <param name="partType">Type of the part.</param> /// <param name="metadata">The metadata discovered on the part.</param> /// <param name="exportedTypes">The exported types.</param> /// <param name="exportingMembers">The exporting members.</param> /// <param name="importingMembers">The importing members.</param> /// <param name="sharingBoundary">The sharing boundary that this part is shared within.</param> /// <param name="onImportsSatisfied">The method to invoke after satisfying imports, if any.</param> /// <param name="importingConstructorRef">The constructor to invoke to construct the part.</param> /// <param name="importingConstructorImports">The importing arguments taken by the importing constructor. <c>null</c> if the part cannot be instantiated.</param> /// <param name="partCreationPolicy">The creation policy for this part.</param> /// <param name="isSharingBoundaryInferred">A value indicating whether the part does not have an explicit sharing boundary, and therefore can obtain its sharing boundary based on its imports.</param> public ComposablePartDefinition(TypeRef partType, IReadOnlyDictionary <string, object> metadata, IReadOnlyCollection <ExportDefinition> exportedTypes, IReadOnlyDictionary <MemberRef, IReadOnlyCollection <ExportDefinition> > exportingMembers, IEnumerable <ImportDefinitionBinding> importingMembers, string sharingBoundary, MethodRef onImportsSatisfied, ConstructorRef importingConstructorRef, IReadOnlyList <ImportDefinitionBinding> importingConstructorImports, CreationPolicy partCreationPolicy, bool isSharingBoundaryInferred = false) { Requires.NotNull(partType, nameof(partType)); Requires.NotNull(metadata, nameof(metadata)); Requires.NotNull(exportedTypes, nameof(exportedTypes)); Requires.NotNull(exportingMembers, nameof(exportingMembers)); Requires.NotNull(importingMembers, nameof(importingMembers)); this.TypeRef = partType; this.Metadata = metadata; this.ExportedTypes = exportedTypes; this.ExportingMembers = exportingMembers; this.ImportingMembers = ImmutableHashSet.CreateRange(importingMembers); this.SharingBoundary = sharingBoundary; this.OnImportsSatisfiedRef = onImportsSatisfied; this.ImportingConstructorRef = importingConstructorRef; this.ImportingConstructorImports = importingConstructorImports; this.CreationPolicy = partCreationPolicy; this.IsSharingBoundaryInferred = isSharingBoundaryInferred; this.ExtraInputAssemblies = Enumerable.Empty <AssemblyName>(); }
protected override ComposablePartDefinition CreatePart(Type partType, bool typeExplicitlyRequested) { Requires.NotNull(partType, nameof(partType)); // 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 (partType.IsAbstract && !partType.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 (partType.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 partType.GetAttributes <ExportAttribute>() select new KeyValuePair <MemberInfo, ExportAttribute>(partType, export); var inheritedExportedTypes = from baseTypeOrInterface in partType.GetInterfaces().Concat(partType.EnumTypeAndBaseTypes().Skip(1)) where baseTypeOrInterface != typeof(object) from export in baseTypeOrInterface.GetAttributes <InheritedExportAttribute>() select new KeyValuePair <MemberInfo, ExportAttribute>(baseTypeOrInterface, 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 && partType.IsAttributeDefined <PartNotDiscoverableAttribute>()) { return(null); } TypeRef partTypeRef = TypeRef.Get(partType, this.Resolver); Type partTypeAsGenericTypeDefinition = partType.IsGenericType ? partType.GetGenericTypeDefinition() : null; // Collect information for all imports. var imports = ImmutableList.CreateBuilder <ImportDefinitionBinding>(); this.AddImportsFromMembers(declaredProperties, declaredFields, partTypeRef, imports); Type baseType = partType.BaseType; while (baseType != null && baseType != typeof(object)) { this.AddImportsFromMembers(baseType.GetProperties(instanceLocal), baseType.GetFields(instanceLocal), partTypeRef, imports); baseType = baseType.BaseType; } var partCreationPolicy = CreationPolicy.Any; var partCreationPolicyAttribute = partType.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) { var method = export.Key as MethodInfo; 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 Type || !partType.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 Type && 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 (!((Type)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 partType.GetAttributes <PartMetadataAttribute>()) { partMetadata[partMetadataAttribute.Name] = partMetadataAttribute.Value; } var exportsOnType = exportDefinitions.Where(kv => kv.Key is Type).Select(kv => kv.Value).ToArray(); var exportsOnMembers = (from kv in exportDefinitions where !(kv.Key is Type) 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), ConstructorRef.Get(importingCtor, this.Resolver), importingCtor != null ? importingConstructorParameters.ToImmutable() : null, // some MEF parts are only for metadata partCreationPolicy, assemblyNamesForMetadataAttributes, partCreationPolicy != CreationPolicy.NonShared)); }