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 void AddImportsFromMembers(PropertyInfo[] declaredProperties, FieldInfo[] declaredFields, TypeRef partTypeRef, IList <ImportDefinitionBinding> imports) { Requires.NotNull(declaredProperties, nameof(declaredProperties)); Requires.NotNull(declaredFields, nameof(declaredFields)); Requires.NotNull(partTypeRef, nameof(partTypeRef)); Requires.NotNull(imports, nameof(imports)); foreach (var member in declaredFields.Concat <MemberInfo>(declaredProperties)) { if (!member.IsStatic()) { if (this.TryCreateImportDefinition(ReflectionHelpers.GetMemberType(member), member, out ImportDefinition importDefinition)) { Type importingSiteType = ReflectionHelpers.GetMemberType(member); var importDefinitionBinding = new ImportDefinitionBinding( importDefinition, partTypeRef, MemberRef.Get(member, this.Resolver), TypeRef.Get(importingSiteType, this.Resolver), TypeRef.Get(GetImportingSiteTypeWithoutCollection(importDefinition, importingSiteType), this.Resolver)); imports.Add(importDefinitionBinding); } } } }
internal static Assignability IsAssignableTo(ImportDefinitionBinding import, ExportDefinitionBinding export) { Requires.NotNull(import, nameof(import)); Requires.NotNull(export, nameof(export)); var receivingTypeRef = import.ImportingSiteElementTypeRef; var exportingTypeRef = export.ExportedValueTypeRef; if (exportingTypeRef.IsGenericTypeDefinition && receivingTypeRef.IsGenericType) { exportingTypeRef = exportingTypeRef.MakeGenericTypeRef(receivingTypeRef.GenericTypeArguments); } // Quick assignability check to attempt to exit early if assignable, otherwise use the slower methods if (receivingTypeRef.IsAssignableFrom(exportingTypeRef)) { return(Assignability.Definitely); } else if (typeof(Delegate).GetTypeInfo().IsAssignableFrom(exportingTypeRef.ResolvedType) && typeof(Delegate).GetTypeInfo().IsAssignableFrom(receivingTypeRef.ResolvedType)) { // Delegates of varying types may be assigned to each other. // For example Action<object, EventArgs> can be assigned to EventHandler. // The simplest way to test for it is to ask the CLR to do it. // http://stackoverflow.com/questions/23075298/how-to-detect-compatibility-between-delegate-types/23088194#23088194 try { Assumes.NotNull(export.ExportingMember); ((MethodInfo)export.ExportingMember).CreateDelegate(receivingTypeRef.ResolvedType, null); return(Assignability.Definitely); } catch (ArgumentException) { return(Assignability.DefinitelyNot); } catch (TargetParameterCountException) { return(Assignability.DefinitelyNot); } } else { bool valueTypeKnownExactly = export.ExportingMemberRef == null || // When [Export] appears on the type itself, we instantiate that exact type. exportingTypeRef.ResolvedType.GetTypeInfo().IsSealed; if (valueTypeKnownExactly) { // There is no way that an exported value can implement the required types to make it assignable. return(Assignability.DefinitelyNot); } if (receivingTypeRef.ResolvedType.GetTypeInfo().IsInterface || exportingTypeRef.ResolvedType.GetTypeInfo().IsAssignableFrom(receivingTypeRef.ResolvedType)) { // The actual exported value at runtime *may* be a derived type that *is* assignable to the import site. return(Assignability.Maybe); } return(Assignability.DefinitelyNot); } }
private static string GetDiagnosticLocation(ImportDefinitionBinding import) { Requires.NotNull(import, nameof(import)); return(string.Format( CultureInfo.CurrentCulture, "{0}.{1}", import.ComposablePartType.FullName, import.ImportingMemberRef == null ? ("ctor(" + import.ImportingParameter.Name + ")") : import.ImportingMember.Name)); }
private void Write(ImportDefinitionBinding importDefinitionBinding) { using (this.Trace("ImportDefinitionBinding")) { this.Write(importDefinitionBinding.ImportDefinition); this.Write(importDefinitionBinding.ComposablePartTypeRef); if (importDefinitionBinding.ImportingMemberRef.IsEmpty) { this.writer.Write(false); this.Write(importDefinitionBinding.ImportingParameterRef); } else { this.writer.Write(true); this.Write(importDefinitionBinding.ImportingMemberRef); } } }
private void Write(ImportDefinitionBinding importDefinitionBinding) { using (this.Trace(nameof(ImportDefinitionBinding))) { this.Write(importDefinitionBinding.ImportDefinition); this.Write(importDefinitionBinding.ComposablePartTypeRef); this.Write(importDefinitionBinding.ImportingSiteTypeRef); this.Write(importDefinitionBinding.ImportingSiteTypeWithoutCollectionRef); if (importDefinitionBinding.ImportingMemberRef == null) { this.writer !.Write(false); this.Write(importDefinitionBinding.ImportingParameterRef); } else { this.writer !.Write(true); this.Write(importDefinitionBinding.ImportingMemberRef); } } }
private void AddImportsFromMembers(PropertyInfo[] declaredProperties, FieldInfo[] declaredFields, TypeRef partTypeRef, IList <ImportDefinitionBinding> imports) { Requires.NotNull(declaredProperties, nameof(declaredProperties)); Requires.NotNull(declaredFields, nameof(declaredFields)); Requires.NotNull(partTypeRef, nameof(partTypeRef)); Requires.NotNull(imports, nameof(imports)); foreach (var member in declaredFields.Concat <MemberInfo>(declaredProperties)) { if (!member.IsStatic()) { try { if (this.TryCreateImportDefinition(ReflectionHelpers.GetMemberType(member), member, out ImportDefinition? importDefinition)) { Type importingSiteType = ReflectionHelpers.GetMemberType(member); var importDefinitionBinding = new ImportDefinitionBinding( importDefinition, partTypeRef, MemberRef.Get(member, this.Resolver), TypeRef.Get(importingSiteType, this.Resolver), TypeRef.Get(GetImportingSiteTypeWithoutCollection(importDefinition, importingSiteType), this.Resolver)); imports.Add(importDefinitionBinding); } } catch (Exception ex) { throw new PartDiscoveryException( string.Format( CultureInfo.CurrentCulture, Strings.PartDiscoveryFailedAtMember, member.Name), ex); } } } }
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)); }
/// <summary> /// Checks whether an import many collection is creatable. /// </summary> internal static bool IsImportManyCollectionTypeCreateable(ImportDefinitionBinding import) { Requires.NotNull(import, nameof(import)); return(IsImportManyCollectionTypeCreateable(import.ImportingSiteType, import.ImportingSiteTypeWithoutCollection)); }