private RuntimeComposition.RuntimeExport?ReadRuntimeExport() { using (this.Trace("RuntimeExport")) { uint id; RuntimeComposition.RuntimeExport?value; if (this.TryPrepareDeserializeReusableObject(out id, out value)) { var contractName = this.ReadString() !; var declaringType = this.ReadTypeRef() !; var member = this.ReadMemberRef(); var exportedValueType = this.ReadTypeRef(); var metadata = this.ReadMetadata(); value = new RuntimeComposition.RuntimeExport( contractName, declaringType, member, exportedValueType, metadata); this.OnDeserializedReusableObject(id, value); } return(value); } }
private void Write(RuntimeComposition.RuntimeExport export) { using (this.Trace("RuntimeExport")) { if (this.TryPrepareSerializeReusableObject(export)) { this.Write(export.ContractName); this.Write(export.DeclaringTypeRef); this.Write(export.MemberRef); this.Write(export.ExportedValueTypeRef); this.Write(export.Metadata); } } }
private object?GetExportedValue(RuntimeComposition.RuntimeImport import, RuntimeComposition.RuntimeExport export, RuntimePartLifecycleTracker?importingPartTracker, bool lazy, out PartLifecycleTracker?partLifecycle) { Requires.NotNull(import, nameof(import)); Requires.NotNull(export, nameof(export)); var exportingRuntimePart = this.composition.GetPart(export); if (this.TryHandleGetExportProvider(exportingRuntimePart, lazy, out object?exportProvider)) { partLifecycle = null; return(exportProvider); } var constructedType = GetPartConstructedTypeRef(exportingRuntimePart, import.Metadata); partLifecycle = this.GetOrCreateValue(import, exportingRuntimePart, exportingRuntimePart.TypeRef, constructedType, importingPartTracker); return(lazy ? ConstructLazyExportedValue(import, export, importingPartTracker, partLifecycle, this.faultCallback) : ConstructExportedValue(import, export, importingPartTracker, partLifecycle, this.faultCallback));
private void ThrowIfExportedValueIsNotAssignableToImport(RuntimeComposition.RuntimeImport import, RuntimeComposition.RuntimeExport export, object?exportedValue) { Requires.NotNull(import, nameof(import)); Requires.NotNull(export, nameof(export)); if (exportedValue != null) { if (!import.ImportingSiteTypeWithoutCollection.GetTypeInfo().IsAssignableFrom(exportedValue.GetType())) { throw new CompositionFailedException( string.Format( CultureInfo.CurrentCulture, Strings.ExportedValueNotAssignableToImport, RuntimeComposition.GetDiagnosticLocation(export), RuntimeComposition.GetDiagnosticLocation(import))); } } }
/// <summary> /// Called from <see cref="GetExportedValue(RuntimeComposition.RuntimeImport, RuntimeComposition.RuntimeExport, RuntimePartLifecycleTracker)"/> /// only, as an assisting method. See remarks. /// </summary> /// <remarks> /// This method is separate from its one caller to avoid a csc.exe compiler bug /// where it captures "this" in the closure for exportedValue, resulting in a memory leak /// which caused one of our GC unit tests to fail. /// </remarks> private ExportedValueConstructor GetExportedValueHelper(RuntimeComposition.RuntimeImport import, RuntimeComposition.RuntimeExport export, RuntimeComposition.RuntimePart exportingRuntimePart, TypeRef originalPartTypeRef, TypeRef constructedPartTypeRef, RuntimePartLifecycleTracker?importingPartTracker) { Requires.NotNull(import, nameof(import)); Requires.NotNull(export, nameof(export)); Requires.NotNull(exportingRuntimePart, nameof(exportingRuntimePart)); Requires.NotNull(originalPartTypeRef, nameof(originalPartTypeRef)); Requires.NotNull(constructedPartTypeRef, nameof(constructedPartTypeRef)); bool nonSharedInstanceRequired = !exportingRuntimePart.IsShared || import.IsNonSharedInstanceRequired; Requires.Argument(importingPartTracker is object || !nonSharedInstanceRequired, nameof(importingPartTracker), "Value required for non-shared parts."); RuntimePartLifecycleTracker?nonSharedPartOwner = nonSharedInstanceRequired && importingPartTracker !.IsNonShared && !import.IsExportFactory ? importingPartTracker : null; PartLifecycleTracker partLifecycle = this.GetOrCreateValue( originalPartTypeRef, constructedPartTypeRef, exportingRuntimePart.SharingBoundary, import.Metadata, nonSharedInstanceRequired, nonSharedPartOwner); var faultCallback = this.faultCallback; Func <object?> exportedValue = () => { try { bool fullyInitializedValueIsRequired = IsFullyInitializedExportRequiredWhenSettingImport(importingPartTracker, import.IsLazy, import.ImportingParameterRef != null); if (!fullyInitializedValueIsRequired && importingPartTracker != null && !import.IsExportFactory) { importingPartTracker.ReportPartiallyInitializedImport(partLifecycle); } if (export.MemberRef != null) { object?part = export.Member !.IsStatic() ? null : (fullyInitializedValueIsRequired ? partLifecycle.GetValueReadyToExpose() : partLifecycle.GetValueReadyToRetrieveExportingMembers()); return(GetValueFromMember(part, export.Member !, import.ImportingSiteElementType, export.ExportedValueTypeRef.Resolve())); }
private ExportedValueConstructor GetExportedValue(RuntimeComposition.RuntimeImport import, RuntimeComposition.RuntimeExport export, RuntimePartLifecycleTracker?importingPartTracker) { Requires.NotNull(import, nameof(import)); Requires.NotNull(export, nameof(export)); var exportingRuntimePart = this.composition.GetPart(export); // Special case importing of ExportProvider if (exportingRuntimePart.TypeRef.Equals(ExportProvider.ExportProviderPartDefinition.TypeRef)) { return(new ExportedValueConstructor(null, () => this.NonDisposableWrapper.Value)); } var constructedType = GetPartConstructedTypeRef(exportingRuntimePart, import.Metadata); return(this.GetExportedValueHelper(import, export, exportingRuntimePart, exportingRuntimePart.TypeRef, constructedType, importingPartTracker)); }
private object CreateExportFactory(RuntimePartLifecycleTracker importingPartTracker, RuntimeComposition.RuntimeImport import, RuntimeComposition.RuntimeExport export) { Requires.NotNull(importingPartTracker, nameof(importingPartTracker)); Requires.NotNull(import, nameof(import)); Requires.NotNull(export, nameof(export)); Type importingSiteElementType = import.ImportingSiteElementType; ImmutableHashSet <string> sharingBoundaries = import.ExportFactorySharingBoundaries.ToImmutableHashSet(); bool newSharingScope = sharingBoundaries.Count > 0; Func <KeyValuePair <object?, IDisposable?> > valueFactory = () => { RuntimeExportProvider scope = newSharingScope ? new RuntimeExportProvider(this.composition, this, sharingBoundaries) : this; var exportedValueConstructor = scope.GetExportedValue(import, export, importingPartTracker); exportedValueConstructor.ExportingPart !.GetValueReadyToExpose(); object?constructedValue = exportedValueConstructor.ValueConstructor(); var disposableValue = newSharingScope ? scope : exportedValueConstructor.ExportingPart as IDisposable; return(new KeyValuePair <object?, IDisposable?>(constructedValue, disposableValue)); }; Type?exportFactoryType = import.ImportingSiteTypeWithoutCollection !; var exportMetadata = export.Metadata; return(this.CreateExportFactory(importingSiteElementType, sharingBoundaries, valueFactory, exportFactoryType, exportMetadata)); }
private object?GetValueForImportElement(RuntimePartLifecycleTracker importingPartTracker, RuntimeComposition.RuntimeImport import, RuntimeComposition.RuntimeExport export, Func <Func <object?>, object, object>?lazyFactory) { if (import.IsExportFactory) { return(this.CreateExportFactory(importingPartTracker, import, export)); } else { if (import.IsLazy) { Requires.NotNull(lazyFactory !, nameof(lazyFactory)); } if (this.composition.GetPart(export).TypeRef.Equals(import.DeclaringTypeRef)) { // This is importing itself. object?part = importingPartTracker.Value; object?value = import.IsLazy ? lazyFactory !(() => part, this.GetStrongTypedMetadata(export.Metadata, import.MetadataType ?? LazyServices.DefaultMetadataViewType)) : part; return(value); } ExportedValueConstructor exportedValueConstructor = this.GetExportedValue(import, export, importingPartTracker); object?importedValue = import.IsLazy ? lazyFactory !(exportedValueConstructor.ValueConstructor, this.GetStrongTypedMetadata(export.Metadata, import.MetadataType ?? LazyServices.DefaultMetadataViewType)) : exportedValueConstructor.ValueConstructor(); return(importedValue); } }
private static object?ConstructExportedValue(RuntimeComposition.RuntimeImport import, RuntimeComposition.RuntimeExport export, RuntimePartLifecycleTracker?importingPartTracker, PartLifecycleTracker partLifecycle, ReportFaultCallback?faultCallback) { Requires.NotNull(import, nameof(import)); Requires.NotNull(export, nameof(export)); Requires.NotNull(partLifecycle, nameof(partLifecycle)); try { bool fullyInitializedValueIsRequired = IsFullyInitializedExportRequiredWhenSettingImport(import.IsLazy, import.ImportingParameterRef != null); if (!fullyInitializedValueIsRequired && importingPartTracker != null && !import.IsExportFactory) { importingPartTracker.ReportPartiallyInitializedImport(partLifecycle); } if (export.MemberRef != null) { object?part = export.Member !.IsStatic() ? null : (fullyInitializedValueIsRequired ? partLifecycle.GetValueReadyToExpose() : partLifecycle.GetValueReadyToRetrieveExportingMembers()); return(GetValueFromMember(part, export.Member !, import.ImportingSiteElementType, export.ExportedValueTypeRef.Resolve())); } else { return(fullyInitializedValueIsRequired ? partLifecycle.GetValueReadyToExpose() : partLifecycle.GetValueReadyToRetrieveExportingMembers()); } } catch (Exception e) { // Let the MEF host know that an exception has been thrown while resolving an exported value faultCallback?.Invoke(e, import, export); throw; } }
static Func <object?> ConstructLazyExportedValue(RuntimeComposition.RuntimeImport import, RuntimeComposition.RuntimeExport export, RuntimePartLifecycleTracker?importingPartTracker, PartLifecycleTracker partLifecycle, ReportFaultCallback?faultCallback) { // Avoid inlining this method into its parent to avoid non-lazy path from paying for capture allocation return(() => ConstructExportedValue(import, export, importingPartTracker, partLifecycle, faultCallback)); }
private object?GetExportedValue(RuntimeComposition.RuntimeImport import, RuntimeComposition.RuntimeExport export, RuntimePartLifecycleTracker?importingPartTracker, out PartLifecycleTracker?partLifecycle) { return(this.GetExportedValue(import, export, importingPartTracker, lazy: false, out partLifecycle)); }
private Func <object?> GetLazyExportedValue(RuntimeComposition.RuntimeImport import, RuntimeComposition.RuntimeExport export, RuntimePartLifecycleTracker?importingPartTracker) { return((Func <object?>) this.GetExportedValue(import, export, importingPartTracker, lazy: true, out _) !); }
/// <summary> /// Called from <see cref="GetExportedValue(RuntimeComposition.RuntimeImport, RuntimeComposition.RuntimeExport, RuntimePartLifecycleTracker)"/> /// only, as an assisting method. See remarks. /// </summary> /// <remarks> /// This method is separate from its one caller to avoid a csc.exe compiler bug /// where it captures "this" in the closure for exportedValue, resulting in a memory leak /// which caused one of our GC unit tests to fail. /// </remarks> private ExportedValueConstructor GetExportedValueHelper(RuntimeComposition.RuntimeImport import, RuntimeComposition.RuntimeExport export, RuntimeComposition.RuntimePart exportingRuntimePart, TypeRef originalPartTypeRef, TypeRef constructedPartTypeRef, RuntimePartLifecycleTracker importingPartTracker) { Requires.NotNull(import, nameof(import)); Requires.NotNull(export, nameof(export)); Requires.NotNull(exportingRuntimePart, nameof(exportingRuntimePart)); Requires.NotNull(originalPartTypeRef, nameof(originalPartTypeRef)); Requires.NotNull(constructedPartTypeRef, nameof(constructedPartTypeRef)); PartLifecycleTracker partLifecycle = this.GetOrCreateValue( originalPartTypeRef, constructedPartTypeRef, exportingRuntimePart.SharingBoundary, import.Metadata, !exportingRuntimePart.IsShared || import.IsNonSharedInstanceRequired); var faultCallback = this.faultCallback; Func <object> exportedValue = () => { try { bool fullyInitializedValueIsRequired = IsFullyInitializedExportRequiredWhenSettingImport(importingPartTracker, import.IsLazy, import.ImportingParameterRef != null); if (!fullyInitializedValueIsRequired && importingPartTracker != null && !import.IsExportFactory) { importingPartTracker.ReportPartiallyInitializedImport(partLifecycle); } if (export.MemberRef != null) { object part = export.Member.IsStatic() ? null : (fullyInitializedValueIsRequired ? partLifecycle.GetValueReadyToExpose() : partLifecycle.GetValueReadyToRetrieveExportingMembers()); return(GetValueFromMember(part, export.Member, import.ImportingSiteElementType, export.ExportedValueTypeRef.Resolve())); } else { return(fullyInitializedValueIsRequired ? partLifecycle.GetValueReadyToExpose() : partLifecycle.GetValueReadyToRetrieveExportingMembers()); } } catch (Exception e) { // Let the MEF host know that an exception has been thrown while resolving an exported value faultCallback?.Invoke(e, import, export); throw; } }; return(new ExportedValueConstructor(partLifecycle, exportedValue)); }