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