diff --git a/src/libraries/System.Composition.TypedParts/src/System/Composition/TypedParts/Discovery/DiscoveredPart.cs b/src/libraries/System.Composition.TypedParts/src/System/Composition/TypedParts/Discovery/DiscoveredPart.cs index 88f005d09ed1e4..5f8e9d05b1264d 100644 --- a/src/libraries/System.Composition.TypedParts/src/System/Composition/TypedParts/Discovery/DiscoveredPart.cs +++ b/src/libraries/System.Composition.TypedParts/src/System/Composition/TypedParts/Discovery/DiscoveredPart.cs @@ -12,6 +12,7 @@ using System.Linq.Expressions; using System.Numerics.Hashing; using System.Reflection; +using System.Threading; namespace System.Composition.TypedParts.Discovery { @@ -31,6 +32,7 @@ internal sealed class DiscoveredPart // Lazily initialised among potentially many exports private ConstructorInfo _constructor; + private ParameterInfo[] _constructorParameters; private CompositeActivator _partActivator; private static readonly IDictionary s_noMetadata = new Dictionary(); @@ -112,7 +114,12 @@ private IEnumerable GetPartActivatorDependencies(Dependen } } - var cps = _constructor.GetParameters(); + // Use LazyInitializer to ensure GetParameters() is called at most once per + // DiscoveredPart instance and the result is safely published to all threads. + // On some runtimes (e.g. Mono on ARM), concurrent calls to GetParameters() + // on the same ConstructorInfo can return different ParameterInfo instances + // due to lazy initialization, causing lookup failures in GetActivator. + var cps = LazyInitializer.EnsureInitialized(ref _constructorParameters, () => _constructor.GetParameters()); for (var i = 0; i < cps.Length; ++i) { @@ -168,7 +175,7 @@ public CompositeActivator GetActivator(IEnumerable depend var contextParam = Expression.Parameter(typeof(LifetimeContext), "cc"); var operationParm = Expression.Parameter(typeof(CompositionOperation), "op"); - var cps = _constructor.GetParameters(); + var cps = LazyInitializer.EnsureInitialized(ref _constructorParameters, _constructor.GetParameters); Expression[] paramActivatorCalls = new Expression[cps.Length]; var partActivatorDependencies = dependencies