public RuntimePartLifecycleTracker(RuntimeExportProvider owningExportProvider, RuntimeComposition.RuntimePart partDefinition, IReadOnlyDictionary <string, object?> importMetadata, PartLifecycleTracker nonSharedPartOwner)
                    : base(owningExportProvider, nonSharedPartOwner)
                {
                    Requires.NotNull(partDefinition, nameof(partDefinition));
                    Requires.NotNull(importMetadata, nameof(importMetadata));

                    this.partDefinition = partDefinition;
                    this.importMetadata = importMetadata;
                }
            private bool TryHandleGetExportProvider(RuntimeComposition.RuntimePart exportingRuntimePart, bool lazy, out object?exportProvider)
            {
                Requires.NotNull(exportingRuntimePart, nameof(exportingRuntimePart));

                // Special case importing of ExportProvider
                if (exportingRuntimePart.TypeRef.Equals(ExportProvider.ExportProviderPartDefinition.TypeRef))
                {
                    exportProvider = lazy ? () => this.NonDisposableWrapper.Value :
                                     this.NonDisposableWrapper.Value;

                    return(true);
                }

                exportProvider = null;
                return(false);
            }
            /// <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);
            }
Beispiel #4
0
            private void Write(RuntimeComposition.RuntimePart part)
            {
                using (this.Trace("RuntimePart"))
                {
                    this.Write(part.TypeRef);
                    this.Write(part.Exports, this.Write);
                    if (part.ImportingConstructorOrFactoryMethodRef == null)
                    {
                        this.writer !.Write(false);
                    }
                    else
                    {
                        this.writer !.Write(true);
                        this.Write(part.ImportingConstructorOrFactoryMethodRef);
                        this.Write(part.ImportingConstructorArguments, this.Write);
                    }

                    this.Write(part.ImportingMembers, this.Write);
                    this.Write(part.OnImportsSatisfiedMethodRefs, this.Write);
                    this.Write(part.SharingBoundary);
                }
            }
            /// <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 PartLifecycleTracker GetOrCreateValue(RuntimeComposition.RuntimeImport import, RuntimeComposition.RuntimePart exportingRuntimePart, TypeRef originalPartTypeRef, TypeRef constructedPartTypeRef, RuntimePartLifecycleTracker?importingPartTracker)
            {
                Requires.NotNull(import, nameof(import));
                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;

                return(this.GetOrCreateValue(
                           originalPartTypeRef,
                           constructedPartTypeRef,
                           exportingRuntimePart.SharingBoundary,
                           import.Metadata,
                           nonSharedInstanceRequired,
                           nonSharedPartOwner));
            }
            /// <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));
            }