public override bool Equals(IReadOnlyDictionary <string, object> x, IReadOnlyDictionary <string, object> y) { if (object.ReferenceEquals(x, y)) { return(true); } // Be sure we're comparing TypeRefs instead of resolved Types to avoid loading assemblies unnecessarily. return(base.Equals(LazyMetadataWrapper.TryUnwrap(x), LazyMetadataWrapper.TryUnwrap(y))); }
protected void Write(IReadOnlyDictionary <string, object> metadata) { using (this.Trace("Metadata")) { this.WriteCompressedUInt((uint)metadata.Count); // Special case certain values to avoid defeating lazy load later. // Check out the ReadMetadata below, how it wraps the return value. var serializedMetadata = new LazyMetadataWrapper(metadata.ToImmutableDictionary(), LazyMetadataWrapper.Direction.ToSubstitutedValue, this.Resolver); foreach (var entry in serializedMetadata) { this.Write(entry.Key); this.WriteObject(entry.Value); } } }
/// <summary> /// Gets the constructed type (non generic type definition) for a part. /// </summary> private static Reflection.TypeRef GetPartConstructedTypeRef(RuntimeComposition.RuntimePart part, IReadOnlyDictionary <string, object?> importMetadata) { Requires.NotNull(part, nameof(part)); Requires.NotNull(importMetadata, nameof(importMetadata)); if (part.TypeRef.IsGenericTypeDefinition) { var bareMetadata = LazyMetadataWrapper.TryUnwrap(importMetadata); object?typeArgsObject; if (bareMetadata.TryGetValue(CompositionConstants.GenericParametersMetadataName, out typeArgsObject) && typeArgsObject is object) { IEnumerable <TypeRef> typeArgs = typeArgsObject is LazyMetadataWrapper.TypeArraySubstitution ? ((LazyMetadataWrapper.TypeArraySubstitution)typeArgsObject).TypeRefArray : ReflectionHelpers.TypesToTypeRefs((Type[])typeArgsObject, part.TypeRef.Resolver); return(part.TypeRef.MakeGenericTypeRef(typeArgs.ToImmutableArray())); } } return(part.TypeRef); }
protected void Write(IReadOnlyDictionary <string, object?> metadata) { using (this.Trace("Metadata")) { this.WriteCompressedUInt((uint)metadata.Count); // Special case certain values to avoid defeating lazy load later. // Check out the ReadMetadata below, how it wraps the return value. IReadOnlyDictionary <string, object?> serializedMetadata; // Unwrap the metadata if its an instance of LazyMetaDataWrapper, the wrapper may end up // implicitly resolving TypeRefs to Types which is undesirable. metadata = LazyMetadataWrapper.TryUnwrap(metadata); serializedMetadata = new LazyMetadataWrapper(metadata.ToImmutableDictionary(), LazyMetadataWrapper.Direction.ToSubstitutedValue, this.Resolver); foreach (var entry in serializedMetadata) { this.Write(entry.Key); this.WriteObject(entry.Value); } } }
internal static void GetInputAssembliesFromMetadata(ISet <AssemblyName> assemblies, IReadOnlyDictionary <string, object> metadata) { Requires.NotNull(assemblies, nameof(assemblies)); Requires.NotNull(metadata, nameof(metadata)); // Get the underlying metadata (should not load the assembly) metadata = LazyMetadataWrapper.TryUnwrap(metadata); foreach (var value in metadata.Values.Where(v => v != null)) { var valueAsType = value as Type; var valueType = value.GetType(); // Check lazy metadata first, then try to get the type data from the value (if not lazy) if (typeof(LazyMetadataWrapper.Enum32Substitution) == valueType) { ((LazyMetadataWrapper.Enum32Substitution)value).EnumType.GetInputAssemblies(assemblies); } else if (typeof(LazyMetadataWrapper.TypeSubstitution) == valueType) { ((LazyMetadataWrapper.TypeSubstitution)value).TypeRef.GetInputAssemblies(assemblies); } else if (typeof(LazyMetadataWrapper.TypeArraySubstitution) == valueType) { foreach (var typeRef in ((LazyMetadataWrapper.TypeArraySubstitution)value).TypeRefArray) { typeRef.GetInputAssemblies(assemblies); } } else if (valueAsType != null) { GetTypeAndBaseTypeAssemblies(assemblies, valueAsType); } else if (value.GetType().IsArray) { // If the value is an array, we should determine the assemblies of each item. var array = value as object[]; if (array != null) { foreach (var obj in array.Where(o => o != null)) { // Check to see if the value is a type. We should get the assembly from // the value if that's the case. var objType = obj as Type; if (objType != null) { GetTypeAndBaseTypeAssemblies(assemblies, objType); } else { GetTypeAndBaseTypeAssemblies(assemblies, obj.GetType()); } } } else { // Array is full of primitives. We can just use value's assembly data GetTypeAndBaseTypeAssemblies(assemblies, value.GetType()); } } else { GetTypeAndBaseTypeAssemblies(assemblies, value.GetType()); } } }
protected virtual LazyMetadataWrapper Clone(LazyMetadataWrapper oldVersion, IReadOnlyDictionary <string, object> newMetadata) { return(new LazyMetadataWrapper(newMetadata.ToImmutableDictionary(), oldVersion.direction, this.resolver)); }
public bool IsSatisfiedBy(ExportDefinition exportDefinition) { Requires.NotNull(exportDefinition, nameof(exportDefinition)); // Fast path since immutable dictionaries are slow to enumerate. if (this.Requirements.IsEmpty) { return(true); } foreach (var entry in this.Requirements) { object value; if (!LazyMetadataWrapper.TryGetLoadSafeValueTypeRef(exportDefinition.Metadata, entry.Key, this.Resolver, out value)) { if (entry.Value.IsMetadataumValueRequired) { return(false); } else { // It's not required, and it's not present. No more validation necessary. continue; } } TypeRef metadatumValueTypeRef = entry.Value.MetadatumValueTypeRef; if (value == null) { if (metadatumValueTypeRef.IsValueType) { // A null reference for a value type is not a compatible match. return(false); } else { // Null is assignable to any reference type. continue; } } if (value is TypeRef valueTypeRef) { if (!metadatumValueTypeRef.ElementTypeRef.IsAssignableFrom(valueTypeRef.ElementTypeRef)) { return(false); } continue; } if (value is TypeRef[] valueTypeRefArray && metadatumValueTypeRef.ElementTypeRef != metadatumValueTypeRef) { var receivingElementTypeRef = metadatumValueTypeRef.ElementTypeRef; foreach (var item in valueTypeRefArray) { if (item == null) { if (receivingElementTypeRef.IsValueType) { return(false); } else { continue; } } if (!receivingElementTypeRef.IsAssignableFrom(item)) { return(false); } } continue; } } return(true); }