private static IReadOnlyDictionary <string, object?> GetExportMetadata(MemberInfo member)
        {
            Requires.NotNull(member, nameof(member));

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

            foreach (var attribute in member.GetAttributes <Attribute>())
            {
                var exportMetadataAttribute = attribute as ExportMetadataAttribute;
                if (exportMetadataAttribute != null)
                {
                    if (exportMetadataAttribute.IsMultiple)
                    {
                        result[exportMetadataAttribute.Name] = AddElement(result.GetValueOrDefault(exportMetadataAttribute.Name) as Array, exportMetadataAttribute.Value, null);
                    }
                    else
                    {
                        result.Add(exportMetadataAttribute.Name, exportMetadataAttribute.Value);
                    }
                }
                else
                {
                    Type attrType = attribute.GetType();

                    // Perf optimization, relies on short circuit evaluation, often a property attribute is an ExportAttribute
                    if (attrType != typeof(ExportAttribute) && attrType.GetTypeInfo().IsAttributeDefined <MetadataAttributeAttribute>(true))
                    {
                        var usage      = attrType.GetTypeInfo().GetFirstAttribute <AttributeUsageAttribute>(true);
                        var properties = attribute.GetType().GetProperties(BindingFlags.Public | BindingFlags.Instance);

                        foreach (var property in properties.Where(p => p.DeclaringType != typeof(Attribute) && p.DeclaringType != typeof(ExportAttribute)))
                        {
                            if (usage != null && usage.AllowMultiple)
                            {
                                result[property.Name] = AddElement(result.GetValueOrDefault(property.Name) as Array, property.GetValue(attribute), ReflectionHelpers.GetMemberType(property));
                            }
                            else
                            {
                                if (result.ContainsKey(property.Name))
                                {
                                    string memberName = member.MemberType.HasFlag(MemberTypes.TypeInfo) || member.MemberType.HasFlag(MemberTypes.NestedType)
                                        ? ((TypeInfo)member).FullName !
                                        : $"{member.DeclaringType?.FullName}.{member.Name}";

                                    throw new NotSupportedException(string.Format(CultureInfo.CurrentCulture, Strings.DiscoveredIdenticalPropertiesInMetadataAttributesForPart, memberName, property.Name));
                                }

                                result.Add(property.Name, property.GetValue(attribute));
                            }
                        }
                    }
                }
            }

            return(result.ToImmutable());
        }
Example #2
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);
                }
            }

            BindingFlags instanceLocal       = BindingFlags.DeclaredOnly | BindingFlags.Instance | this.PublicVsNonPublicFlags;
            var          declaredProperties  = partTypeInfo.GetProperties(instanceLocal);
            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> >();

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

            var imports = ImmutableList.CreateBuilder <ImportDefinitionBinding>();

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

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

            void AddImportsFromMembers(PropertyInfo[] declaredProperties, TypeRef partTypeRef, IList <ImportDefinitionBinding> imports)
            {
                foreach (var member in declaredProperties)
                {
                    try
                    {
                        var importAttribute     = member.GetFirstAttribute <ImportAttribute>();
                        var importManyAttribute = member.GetFirstAttribute <ImportManyAttribute>();
                        Requires.Argument(!(importAttribute != null && importManyAttribute != null), nameof(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,
                                partTypeRef,
                                MemberRef.Get(member, this.Resolver),
                                TypeRef.Get(member.PropertyType, this.Resolver),
                                TypeRef.Get(GetImportingSiteTypeWithoutCollection(importDefinition, member.PropertyType), this.Resolver));
                            imports.Add(importDefinitionBinding);
                        }
                    }
                    catch (Exception ex)
                    {
                        throw ThrowErrorScanningMember(member, ex);
                    }
                }
            }

            // MEFv2 is willing to find `internal` OnImportsSatisfied methods, so we should too regardless of our NonPublic flag.
            var  onImportsSatisfied = ImmutableList.CreateBuilder <MethodRef>();
            Type?currentType        = partTypeInfo;

            while (currentType is object && currentType != typeof(object))
            {
                foreach (var method in currentType.GetMethods(BindingFlags.DeclaredOnly | BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance))
                {
                    try
                    {
                        if (method.IsAttributeDefined <OnImportsSatisfiedAttribute>())
                        {
                            Verify.Operation(method.GetParameters().Length == 0, Strings.OnImportsSatisfiedTakeNoParameters);
                            onImportsSatisfied.Add(MethodRef.Get(method, this.Resolver));
                        }
                    }
                    catch (Exception ex)
                    {
                        throw ThrowErrorScanningMember(method, ex);
                    }
                }

                currentType = currentType.GetTypeInfo().BaseType;
            }

            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,
                       onImportsSatisfied.ToImmutable(),
                       MethodRef.Get(importingCtor, this.Resolver),
                       importingConstructorParameters.ToImmutable(),
                       partCreationPolicy,
                       isSharingBoundaryInferred: false,
                       extraInputAssemblies: assemblyNamesForMetadataAttributes));
        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));
        }
Example #4
0
        public IEnumerable <ComposedPartDiagnostic> Validate(IReadOnlyDictionary <Type, ExportDefinitionBinding> metadataViews)
        {
            Requires.NotNull(metadataViews, nameof(metadataViews));

            if (this.Definition.ExportDefinitions.Any(ed => CompositionConfiguration.ExportDefinitionPracticallyEqual.Default.Equals(ExportProvider.ExportProviderExportDefinition, ed.Value)) &&
                !this.Definition.Equals(ExportProvider.ExportProviderPartDefinition))
            {
                yield return(new ComposedPartDiagnostic(this, Strings.ExportOfExportProviderNotAllowed, this.Definition.Type.FullName));
            }

            var importsWithGenericTypeParameters = this.Definition.Imports
                                                   .Where(import => import.ImportingSiteElementType.GetTypeInfo().ContainsGenericParameters).ToList();

            foreach (var import in importsWithGenericTypeParameters)
            {
                yield return(new ComposedPartDiagnostic(
                                 this,
                                 Strings.ImportsThatUseGenericTypeParametersNotSupported,
                                 GetDiagnosticLocation(import)));
            }

            foreach (var pair in this.SatisfyingExports)
            {
                var importDefinition = pair.Key.ImportDefinition;
                switch (importDefinition.Cardinality)
                {
                case ImportCardinality.ExactlyOne:
                    if (pair.Value.Count != 1)
                    {
                        yield return(new ComposedPartDiagnostic(
                                         this,
                                         Strings.ExpectedExactlyOneExportButFound,
                                         GetDiagnosticLocation(pair.Key),
                                         pair.Key.ImportingSiteElementType,
                                         pair.Value.Count,
                                         GetExportsList(pair.Value)));
                    }

                    break;

                case ImportCardinality.OneOrZero:
                    if (pair.Value.Count > 1)
                    {
                        yield return(new ComposedPartDiagnostic(
                                         this,
                                         Strings.ExpectedOneOrZeroExportsButFound,
                                         GetDiagnosticLocation(pair.Key),
                                         pair.Key.ImportingSiteElementType,
                                         pair.Value.Count,
                                         GetExportsList(pair.Value)));
                    }

                    break;
                }

                foreach (var export in pair.Value)
                {
                    if (ReflectionHelpers.IsAssignableTo(pair.Key, export) == ReflectionHelpers.Assignability.DefinitelyNot)
                    {
                        yield return(new ComposedPartDiagnostic(
                                         this,
                                         Strings.IsNotAssignableFromExportedMEFValue,
                                         GetDiagnosticLocation(pair.Key),
                                         GetDiagnosticLocation(export)));
                    }

                    // Some parts exist exclusively for their metadata and the parts themselves are not instantiable.
                    // But that only makes sense if all importers do it lazily. If this part imports one of these
                    // non-instantiable parts in a non-lazy fashion, it's doomed to fail at runtime, so call it a graph error.
                    if (!pair.Key.IsLazy && !export.IsStaticExport && !export.PartDefinition.IsInstantiable)
                    {
                        // Special case around our export provider.
                        if (export.ExportDefinition != ExportProvider.ExportProviderExportDefinition)
                        {
                            yield return(new ComposedPartDiagnostic(
                                             this,
                                             Strings.CannotImportBecauseExportingPartCannotBeInstantiated,
                                             GetDiagnosticLocation(pair.Key),
                                             GetDiagnosticLocation(export)));
                        }
                    }
                }

                if (pair.Key.ImportDefinition.Cardinality == ImportCardinality.ZeroOrMore && !pair.Key.ImportingParameterRef.IsEmpty && !IsAllowedImportManyParameterType(pair.Key.ImportingParameterRef.Resolve().ParameterType))
                {
                    yield return(new ComposedPartDiagnostic(this, Strings.ImportingCtorHasUnsupportedParameterTypeForImportMany));
                }

                var metadataType = pair.Key.MetadataType;
                if (metadataType != null && !metadataViews.ContainsKey(metadataType))
                {
                    yield return(new ComposedPartDiagnostic(
                                     this,
                                     Strings.MetadataTypeNotSupported,
                                     GetDiagnosticLocation(pair.Key),
                                     metadataType.FullName));
                }
            }
        }
 public ImportDefinitionBinding(ImportDefinition importDefinition, TypeRef composablePartType, MemberRef importingMember)
     : this(
         importDefinition,
         composablePartType,
         importingMember,
         TypeRef.Get(ReflectionHelpers.GetMemberType(importingMember.MemberInfo), importingMember.Resolver),
         TypeRef.Get(importDefinition.Cardinality == ImportCardinality.ZeroOrMore ? PartDiscovery.GetElementTypeFromMany(ReflectionHelpers.GetMemberType(importingMember.MemberInfo)) : ReflectionHelpers.GetMemberType(importingMember.MemberInfo), importingMember.Resolver))
 {
 }
        private ImmutableDictionary <string, object> GetExportMetadata(ICustomAttributeProvider member)
        {
            Requires.NotNull(member, nameof(member));

            var result = ImmutableDictionary.CreateBuilder <string, object>();
            var namesOfMetadataWithMultipleValues = new HashSet <string>(StringComparer.Ordinal);

            foreach (var attribute in member.GetAttributes <Attribute>())
            {
                var attrType = attribute.GetType().GetTypeInfo();
                var exportMetadataAttribute = attribute as ExportMetadataAttribute;
                if (exportMetadataAttribute != null)
                {
                    UpdateMetadataDictionary(result, namesOfMetadataWithMultipleValues, exportMetadataAttribute.Name, exportMetadataAttribute.Value, null);
                }
                else
                {
                    // Perf optimization, relies on short circuit evaluation, often a property attribute is an ExportAttribute
                    if (attrType != typeof(ExportAttribute).GetTypeInfo() && attrType.IsAttributeDefined <MetadataAttributeAttribute>())
                    {
                        var properties = attrType.GetProperties(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance);
                        foreach (var property in properties.Where(p => p.DeclaringType != typeof(Attribute)))
                        {
                            UpdateMetadataDictionary(result, namesOfMetadataWithMultipleValues, property.Name, property.GetValue(attribute), ReflectionHelpers.GetMemberType(property));
                        }
                    }
                }
            }

            return(result.ToImmutable());
        }
        private static XDocument CreateDgml(ISet <ComposedPart> parts)
        {
            Requires.NotNull(parts, nameof(parts));

            XElement nodes, links;
            var      dgml = Dgml.Create(out nodes, out links, direction: "RightToLeft")
                            .WithStyle(
                "ExportFactory",
                new Dictionary <string, string>
            {
                { "StrokeDashArray", "2,2" },
            },
                "Link")
                            .WithStyle(
                "VsMEFBuiltIn",
                new Dictionary <string, string>
            {
                { "Visibility", "Hidden" },
            });

            foreach (string sharingBoundary in parts.Select(p => p.Definition.SharingBoundary).Distinct())
            {
                if (!string.IsNullOrEmpty(sharingBoundary))
                {
                    nodes.Add(Dgml.Node(sharingBoundary, sharingBoundary, "Expanded"));
                }
            }

            foreach (var part in parts)
            {
                var node = Dgml.Node(part.Definition.Id, ReflectionHelpers.GetTypeName(part.Definition.Type, false, true, null, null));
                if (!string.IsNullOrEmpty(part.Definition.SharingBoundary))
                {
                    node.ContainedBy(part.Definition.SharingBoundary, dgml);
                }

                string[] partDgmlCategories;
                if (part.Definition.Metadata.TryGetValue(CompositionConstants.DgmlCategoryPartMetadataName, out partDgmlCategories))
                {
                    node = node.WithCategories(partDgmlCategories);
                }

                nodes.Add(node);
                foreach (var import in part.SatisfyingExports.Keys)
                {
                    foreach (ExportDefinitionBinding export in part.SatisfyingExports[import])
                    {
                        string linkLabel = !export.ExportedValueTypeRef.Equals(export.PartDefinition.TypeRef)
                            ? export.ExportedValueType.ToString()
                            : null;
                        var link = Dgml.Link(export.PartDefinition.Id, part.Definition.Id, linkLabel);
                        if (import.IsExportFactory)
                        {
                            link = link.WithCategories("ExportFactory");
                        }

                        links.Add(link);
                    }
                }
            }

            return(dgml);
        }
Example #8
0
        internal void GetInputAssemblies(ISet <AssemblyName> assemblies)
        {
            Requires.NotNull(assemblies, nameof(assemblies));

            ReflectionHelpers.GetInputAssembliesFromMetadata(assemblies, this.Metadata);
        }
        private static ImmutableDictionary <string, MetadatumRequirement> GetRequiredMetadata(TypeRef metadataViewRef, Resolver resolver)
        {
            Requires.NotNull(metadataViewRef, nameof(metadataViewRef));
            Requires.NotNull(resolver, nameof(resolver));

            var  metadataView = metadataViewRef.Resolve();
            bool hasMetadataViewImplementation = MetadataViewImplProxy.HasMetadataViewImplementation(metadataView);

            if (metadataView.GetTypeInfo().IsInterface&& !metadataView.Equals(typeof(IDictionary <string, object>)) && !metadataView.Equals(typeof(IReadOnlyDictionary <string, object>)))
            {
                var requiredMetadata = ImmutableDictionary.CreateBuilder <string, MetadatumRequirement>();

                foreach (var property in metadataView.EnumProperties().WherePublicInstance())
                {
                    bool required = !property.IsAttributeDefined <DefaultValueAttribute>();

                    // Ignore properties that have a default value and have a metadataview implementation.
                    if (required || !hasMetadataViewImplementation)
                    {
                        requiredMetadata.Add(property.Name, new MetadatumRequirement(TypeRef.Get(ReflectionHelpers.GetMemberType(property), resolver), required));
                    }
                }

                return(requiredMetadata.ToImmutable());
            }

            return(ImmutableDictionary <string, MetadatumRequirement> .Empty);
        }
        public void ToString(TextWriter writer)
        {
            var indentingWriter = IndentingTextWriter.Get(writer);

            foreach (var requirement in this.Requirements)
            {
                indentingWriter.WriteLine("{0} = {1} (required: {2})", requirement.Key, ReflectionHelpers.GetTypeName(requirement.Value.MetadatumValueType, false, true, null, null), requirement.Value.IsMetadataumValueRequired);
            }
        }