Пример #1
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));
            }
        }
Пример #2
0
        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);
                    }
                }
            }
        }
Пример #3
0
        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);
            }
        }
Пример #4
0
        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));
        }
Пример #5
0
 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);
         }
     }
 }
Пример #6
0
            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);
                    }
                }
            }
Пример #7
0
        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);
                    }
                }
            }
        }
Пример #8
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));
        }
Пример #9
0
 /// <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));
 }