|
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Reflection;
using System.Reflection.Runtime.General;
using System.Reflection.Runtime.ParameterInfos;
using System.Reflection.Runtime.TypeInfos;
using System.Text;
using Internal.Reflection.Core;
using Internal.Reflection.Core.Execution;
namespace System.Reflection.Runtime.MethodInfos
{
internal static class RuntimeMethodHelpers
{
//
// Returns the ParameterInfo objects for the method parameters and return parameter.
//
// The ParameterInfo objects will report "contextMethod" as their Member property and use it to get type variable information from
// the contextMethod's declaring type. The actual metadata, however, comes from "this."
//
// The methodTypeArguments provides the fill-ins for any method type variable elements in the parameter type signatures.
//
// Does not array-copy.
//
internal static RuntimeParameterInfo[] GetRuntimeParameters<TRuntimeMethodCommon>(ref TRuntimeMethodCommon runtimeMethodCommon, MethodBase contextMethod, RuntimeTypeInfo[] methodTypeArguments, out RuntimeParameterInfo returnParameter)
where TRuntimeMethodCommon : IRuntimeMethodCommon<TRuntimeMethodCommon>, IEquatable<TRuntimeMethodCommon>
{
TypeContext typeContext = contextMethod.DeclaringType.ToRuntimeTypeInfo().TypeContext;
typeContext = new TypeContext(typeContext.GenericTypeArguments, methodTypeArguments);
QSignatureTypeHandle[] typeSignatures = runtimeMethodCommon.QualifiedMethodSignature;
int count = typeSignatures.Length;
VirtualRuntimeParameterInfoArray result = new VirtualRuntimeParameterInfoArray(count);
runtimeMethodCommon.FillInMetadataDescribedParameters(ref result, typeSignatures, contextMethod, typeContext);
for (int i = 0; i < count; i++)
{
if (result[i] == null)
{
result[i] =
RuntimeThinMethodParameterInfo.GetRuntimeThinMethodParameterInfo(
contextMethod,
i - 1,
typeSignatures[i],
typeContext);
}
}
returnParameter = result.First;
return result.Remainder;
}
// Compute the ToString() value in a pay-to-play-safe way.
internal static string ComputeToString<TRuntimeMethodCommon>(ref TRuntimeMethodCommon runtimeMethodCommon, MethodBase contextMethod, RuntimeTypeInfo[] methodTypeArguments)
where TRuntimeMethodCommon : IRuntimeMethodCommon<TRuntimeMethodCommon>, IEquatable<TRuntimeMethodCommon>
{
RuntimeParameterInfo returnParameter;
RuntimeParameterInfo[] parameters = GetRuntimeParameters(ref runtimeMethodCommon, contextMethod, methodTypeArguments, out returnParameter);
return ComputeToString(contextMethod, methodTypeArguments, parameters, returnParameter);
}
// Used by method and property ToString() methods to display the list of parameter types. Replicates the behavior of MethodBase.ConstructParameters()
// but in a pay-to-play-safe way.
internal static string ComputeParametersString(RuntimeParameterInfo[] parameters)
{
StringBuilder sb = new StringBuilder(30);
for (int i = 0; i < parameters.Length; i++)
{
if (i != 0)
sb.Append(", ");
string parameterTypeString = parameters[i].ParameterType.FormatTypeName();
// Legacy: Why use "ByRef" for by ref parameters? What language is this?
// VB uses "ByRef" but it should precede (not follow) the parameter name.
// Why don't we just use "&"?
if (parameterTypeString.EndsWith('&'))
{
sb.Append(parameterTypeString, 0, parameterTypeString.Length - 1);
sb.Append(" ByRef");
}
else
{
sb.Append(parameterTypeString);
}
}
return sb.ToString();
}
internal static string ComputeToString(MethodBase contextMethod, RuntimeTypeInfo[] methodTypeArguments, RuntimeParameterInfo[] parameters, RuntimeParameterInfo returnParameter)
{
StringBuilder sb = new StringBuilder(30);
sb.Append(returnParameter == null ? "Void" : returnParameter.ParameterType.FormatTypeName()); // ConstructorInfos allowed to pass in null rather than craft a ReturnParameterInfo that's always of type void.
sb.Append(' ');
sb.Append(contextMethod.Name);
if (methodTypeArguments.Length != 0)
{
string sep = "";
sb.Append('[');
foreach (RuntimeTypeInfo methodTypeArgument in methodTypeArguments)
{
sb.Append(sep);
sep = ",";
sb.Append(methodTypeArgument.Name);
}
sb.Append(']');
}
sb.Append('(');
sb.Append(ComputeParametersString(parameters));
sb.Append(')');
return sb.ToString();
}
}
}
|