Esempio n. 1
0
        internal static string GetTypeIdentity(Type type, bool formatGenericName)
        {
            Assumes.NotNull(type);
            string typeIdentity = null;

            if (!TypeIdentityCache.TryGetValue(type, out typeIdentity))
            {
                if (!type.GetTypeInfo().IsAbstract&& type.HasBaseclassOf(typeof(Delegate)))
                {
                    MethodInfo method = type.GetTypeInfo().GetDeclaredMethod("Invoke");
                    typeIdentity = ContractNameServices.GetTypeIdentityFromMethod(method);
                }
                else if (type.IsGenericParameter)
                {
                    StringBuilder typeIdentityStringBuilder = new StringBuilder();
                    WriteTypeArgument(typeIdentityStringBuilder, false, type, formatGenericName);
                    typeIdentityStringBuilder.Remove(typeIdentityStringBuilder.Length - 1, 1);
                    typeIdentity = typeIdentityStringBuilder.ToString();
                }
                else
                {
                    StringBuilder typeIdentityStringBuilder = new StringBuilder();
                    WriteTypeWithNamespace(typeIdentityStringBuilder, type, formatGenericName);
                    typeIdentity = typeIdentityStringBuilder.ToString();
                }

                Assumes.True(!string.IsNullOrEmpty(typeIdentity));
                TypeIdentityCache.Add(type, typeIdentity);
            }

            return(typeIdentity);
        }
Esempio n. 2
0
        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.GetTypeInfo().GetConstructors(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance).Single(c => c.GetParameters().Length == 0), resolver),
                ImmutableList <ImportDefinitionBinding> .Empty,
                CreationPolicy.Shared,
                false);

            return(partDefinition);
        }
Esempio n. 3
0
        private static ImmutableDictionary <Type, ExportDefinitionBinding> GetMetadataViewProvidersMap(ComposableCatalog customizedCatalog)
        {
            Requires.NotNull(customizedCatalog, nameof(customizedCatalog));

            var providers = (
                from part in customizedCatalog.Parts
                from export in part.ExportDefinitions
                where export.Value.ContractName == ContractNameServices.GetTypeIdentity(typeof(IMetadataViewProvider))
                orderby ExportProvider.GetOrderMetadata(export.Value.Metadata) descending
                let exportDefinitionBinding = new ExportDefinitionBinding(export.Value, part, default(MemberRef))
                                              let provider = (IMetadataViewProvider)part.ImportingConstructorOrFactory !.Instantiate(Type.EmptyTypes)
                                                             select Tuple.Create(provider, exportDefinitionBinding)).ToList();

            var metadataTypes = new HashSet <Type>(
                from part in customizedCatalog.Parts
                from import in part.Imports
                where import.MetadataType != null
                select import.MetadataType);

            // Make sure that a couple of "primitive" metadata types are included.
            metadataTypes.Add(typeof(IDictionary <string, object>));
            metadataTypes.Add(typeof(IReadOnlyDictionary <string, object>));

            // Find metadata view providers for each metadata type.
            // Don't worry about the ones we can't find. Part validation happens later
            // and they will notice when metadata view providers aren't available and create errors at that time.
            var metadataViewsAndProviders = ImmutableDictionary.CreateBuilder <Type, ExportDefinitionBinding>();

            foreach (var metadataType in metadataTypes)
            {
                var provider = providers.FirstOrDefault(p => p.Item1.IsMetadataViewSupported(metadataType));
                if (provider != null)
                {
                    metadataViewsAndProviders.Add(metadataType, provider.Item2);
                }
            }

            return(metadataViewsAndProviders.ToImmutable());
        }
Esempio n. 4
0
        private static ExportDefinition CreateExportDefinition(ImmutableDictionary <string, object?> memberExportMetadata, ExportAttribute exportAttribute, Type exportedType)
        {
            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);

            return(exportDefinition);
        }
Esempio n. 5
0
 protected internal static string GetContractName(Type type)
 {
     return(ContractNameServices.GetTypeIdentity(type));
 }
        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));
        }
        public static ImmutableDictionary <string, object> GetExportMetadata(Type type)
        {
            Requires.NotNull(type, nameof(type));

            return(GetExportMetadata(ContractNameServices.GetTypeIdentity(type)));
        }
 public ExportTypeIdentityConstraint(Type typeIdentity)
 {
     Requires.NotNull(typeIdentity, nameof(typeIdentity));
     this.TypeIdentityName = ContractNameServices.GetTypeIdentity(typeIdentity);
 }