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