diff --git a/src/System.Management.Automation/engine/CoreAdapter.cs b/src/System.Management.Automation/engine/CoreAdapter.cs index 7343daef7bd..813f612a744 100644 --- a/src/System.Management.Automation/engine/CoreAdapter.cs +++ b/src/System.Management.Automation/engine/CoreAdapter.cs @@ -2345,7 +2345,7 @@ internal class MethodCacheEntry /// /// Cache delegate to the ctor of PSMethod<> with a template parameter derived from the methodInformationStructures. /// - internal Func psmethodCtor; + internal Func PSMethodCtor; internal MethodCacheEntry(MethodBase[] methods) { diff --git a/src/System.Management.Automation/engine/LanguagePrimitives.cs b/src/System.Management.Automation/engine/LanguagePrimitives.cs index 9892dfc368b..a55261e5c04 100644 --- a/src/System.Management.Automation/engine/LanguagePrimitives.cs +++ b/src/System.Management.Automation/engine/LanguagePrimitives.cs @@ -11,6 +11,7 @@ using System.Linq.Expressions; using System.Management.Automation.Language; using System.Reflection; +using System.Reflection.Emit; using System.Runtime.CompilerServices; using System.Text.RegularExpressions; using System.Xml; @@ -20,7 +21,7 @@ using System.Management.Automation.Runspaces; using System.Diagnostics.CodeAnalysis; // for fxcop using Dbg = System.Management.Automation.Diagnostics; -using System.Reflection.Emit; +using MethodCacheEntry = System.Management.Automation.DotNetAdapter.MethodCacheEntry; #if !CORECLR // System.DirectoryServices are not in CoreCLR @@ -3210,31 +3211,24 @@ private static Delegate ConvertPSMethodInfoToDelegate(object valueToConvert, IFormatProvider formatProvider, TypeTable backupTable) { - PSMethod psMethod; + // We can only possibly convert PSMethod instance of the type PSMethod. + // Such a PSMethod essentially represents a set of .NET method overloads. + var psMethod = (PSMethod)valueToConvert; + try { - psMethod = (PSMethod) valueToConvert; - - var maybeType = psMethod.instance as Type; - var methodInfoCandiates = maybeType != null - ? maybeType.GetMethods(BindingFlags.Static | BindingFlags.Public) - : psMethod.instance.GetType().GetMethods(BindingFlags.Instance | BindingFlags.Public); - + var methods = (MethodCacheEntry)psMethod.adapterData; + var isStatic = psMethod.instance is Type; var targetMethodInfo = resultType.GetMethod("Invoke"); - var comparator = new DelegateArgsComparator(targetMethodInfo); - foreach (var candidate in methodInfoCandiates) + foreach (var methodInformation in methods.methodInformationStructures) { - if (candidate.Name != psMethod.Name) - { - continue; - } + var candidate = (MethodInfo)methodInformation.method; if (comparator.SignatureMatches(candidate.ReturnType, candidate.GetParameters())) { - return maybeType != null - ? candidate.CreateDelegate(resultType) - : candidate.CreateDelegate(resultType, psMethod.instance); + return isStatic ? candidate.CreateDelegate(resultType) + : candidate.CreateDelegate(resultType, psMethod.instance); } } } @@ -3246,12 +3240,12 @@ private static Delegate ConvertPSMethodInfoToDelegate(object valueToConvert, valueToConvert.ToString(), resultType.ToString(), e.Message); } - var msg = String.Format(ExtendedTypeSystem.PSMethodToDelegateNoMatchingOverLoad, psMethod, resultType); + var msg = String.Format(ExtendedTypeSystem.PSMethodToDelegateNoMatchingOverLoad, psMethod, resultType); typeConversion.WriteLine($"PSMethod to Delegate exception: \"{msg}\"."); throw new PSInvalidCastException("InvalidCastExceptionPSMethodToDelegate", null, ExtendedTypeSystem.InvalidCastExceptionWithInnerException, valueToConvert.ToString(), resultType.ToString(), msg); - } + } private static object ConvertToNullable(object valueToConvert, Type resultType, @@ -4789,7 +4783,6 @@ private static ConversionData FigureLanguageConversion(Type fromType, Type toTyp while (signatureEnumerator.MoveNext()) { var candidate = signatureEnumerator.Current.GetMethod("Invoke"); - if (comparator.SignatureMatches(candidate.ReturnType, candidate.GetParameters())) { return CacheConversion(fromType, toType, LanguagePrimitives.ConvertPSMethodInfoToDelegate, ConversionRank.Language); @@ -4824,7 +4817,7 @@ private bool ReturnTypeMatches(Type returnType) private bool ParameterTypesMatches(ParameterInfo[] arguments) { var argsCount = _targetParametersInfos.Length; - // void is encoded as typeof(Unit) in the PSMethod> as the last parameter + // void is encoded as typeof(VOID) in the PSMethod> as the last parameter if (arguments.Length != argsCount) { return false; diff --git a/src/System.Management.Automation/engine/MshMemberInfo.cs b/src/System.Management.Automation/engine/MshMemberInfo.cs index 223208a9213..0890f0c7e37 100644 --- a/src/System.Management.Automation/engine/MshMemberInfo.cs +++ b/src/System.Management.Automation/engine/MshMemberInfo.cs @@ -2642,11 +2642,17 @@ internal static PSMethod Create(string name, DotNetAdapter dotNetInstanceAdapter internal static PSMethod Create(string name, DotNetAdapter dotNetInstanceAdapter, object baseObject, DotNetAdapter.MethodCacheEntry method, bool isSpecial, bool isHidden) { - if (method.psmethodCtor == null) + if (method[0].method is ConstructorInfo) { - method.psmethodCtor = CreatePSMethodConstructor(method.methodInformationStructures); + // Constructor cannot be converted to a delegate, so just return a simple PSMethod instance + return new PSMethod(name, dotNetInstanceAdapter, baseObject, method, isSpecial, isHidden); } - return method.psmethodCtor.Invoke(name, dotNetInstanceAdapter, baseObject, method, isSpecial, isHidden); + + if (method.PSMethodCtor == null) + { + method.PSMethodCtor = CreatePSMethodConstructor(method.methodInformationStructures); + } + return method.PSMethodCtor.Invoke(name, dotNetInstanceAdapter, baseObject, method, isSpecial, isHidden); } static Type GetMethodGroupType(MethodInfo methodInfo) @@ -2697,7 +2703,7 @@ private static Type GetPSMethodTypeProjection(Type type, bool isOut = false) { if (type == typeof(void)) { - return typeof(Unit); + return typeof(VOID); } if (type == typeof(TypedReference)) { @@ -2742,7 +2748,7 @@ internal static bool MatchesPSMethodProjectedType(Type targetType, Type projecte sourceType = sourceType.GenericTypeArguments[0]; } - if (targetType == typeof(void) && sourceType == typeof(Unit)) + if (targetType == typeof(void) && sourceType == typeof(VOID)) { return true; } @@ -2783,21 +2789,14 @@ private static MethodInfo ReplaceGenericTypeArgumentsWithMarkerTypes(MethodInfo private static Func CreatePSMethodConstructor(MethodInformation[] methods) { + // Produce the PSMethod creator for MethodInfo objects var types = new Type[methods.Length]; for (int i = 0; i < methods.Length; i++) { - var mb = methods[i].method; - - if (mb is MethodInfo mi) - { - types[i] = GetMethodGroupType(mi); - } - else - { - types[i] = typeof(Unit); - } + types[i] = GetMethodGroupType((MethodInfo)methods[i].method); } - var methodGroupType = CreateMethodGroup(types, 0, types.Length); + + var methodGroupType = CreateMethodGroup(types, 0, types.Length); Type psMethodType = typeof(PSMethod<>).MakeGenericType(methodGroupType); var delegateType = typeof(Func); return (Func)Delegate.CreateDelegate(delegateType, psMethodType.GetMethod("Create", BindingFlags.NonPublic|BindingFlags.Static)); @@ -2946,9 +2945,9 @@ internal class MethodGroup : MethodGroup { } internal class MethodGroup : MethodGroup { } internal class MethodGroup : MethodGroup { } - class Unit + class VOID { - private Unit() { } + private VOID() { } } internal struct PSMethodSignatureEnumerator : IEnumerator