2008-11-14 10:40:49 +03:00
|
|
|
|
/*
|
2009-05-17 09:59:24 +04:00
|
|
|
|
Copyright (C) 2008, 2009 Jeroen Frijters
|
2008-11-14 10:40:49 +03:00
|
|
|
|
|
|
|
|
|
This software is provided 'as-is', without any express or implied
|
|
|
|
|
warranty. In no event will the authors be held liable for any damages
|
|
|
|
|
arising from the use of this software.
|
|
|
|
|
|
|
|
|
|
Permission is granted to anyone to use this software for any purpose,
|
|
|
|
|
including commercial applications, and to alter it and redistribute it
|
|
|
|
|
freely, subject to the following restrictions:
|
|
|
|
|
|
|
|
|
|
1. The origin of this software must not be misrepresented; you must not
|
|
|
|
|
claim that you wrote the original software. If you use this software
|
|
|
|
|
in a product, an acknowledgment in the product documentation would be
|
|
|
|
|
appreciated but is not required.
|
|
|
|
|
2. Altered source versions must be plainly marked as such, and must not be
|
|
|
|
|
misrepresented as being the original software.
|
|
|
|
|
3. This notice may not be removed or altered from any source distribution.
|
|
|
|
|
|
|
|
|
|
Jeroen Frijters
|
|
|
|
|
jeroen@frijters.net
|
|
|
|
|
|
|
|
|
|
*/
|
|
|
|
|
using System;
|
|
|
|
|
using System.Reflection;
|
|
|
|
|
using System.IO;
|
|
|
|
|
using System.Diagnostics;
|
|
|
|
|
using IKVM.Reflection.Emit.Writer;
|
|
|
|
|
using System.Collections.Generic;
|
|
|
|
|
using System.Runtime.InteropServices;
|
|
|
|
|
using System.Runtime.CompilerServices;
|
|
|
|
|
using System.Diagnostics.SymbolStore;
|
|
|
|
|
|
|
|
|
|
namespace IKVM.Reflection.Emit
|
|
|
|
|
{
|
|
|
|
|
public sealed class MethodBuilder : MethodInfo
|
|
|
|
|
{
|
|
|
|
|
private readonly TypeBuilder typeBuilder;
|
|
|
|
|
private readonly string name;
|
|
|
|
|
private readonly int nameIndex;
|
|
|
|
|
private readonly int pseudoToken;
|
2009-06-23 13:04:10 +04:00
|
|
|
|
private int signature;
|
|
|
|
|
private Type returnType;
|
|
|
|
|
private Type[] parameterTypes;
|
|
|
|
|
private Type[][] requiredCustomModifiers; // last element is for the return type
|
|
|
|
|
private Type[][] optionalCustomModifiers;
|
2008-11-14 10:40:49 +03:00
|
|
|
|
private MethodAttributes attributes;
|
|
|
|
|
private MethodImplAttributes implFlags;
|
|
|
|
|
private ILGenerator ilgen;
|
|
|
|
|
private int rva;
|
2009-06-23 13:04:10 +04:00
|
|
|
|
private readonly CallingConventions callingConvention;
|
2008-11-14 10:40:49 +03:00
|
|
|
|
private List<ParameterBuilder> parameters;
|
2009-06-23 13:06:51 +04:00
|
|
|
|
private GenericTypeParameterBuilder[] gtpb;
|
2009-11-09 09:38:30 +03:00
|
|
|
|
private List<CustomAttributeBuilder> declarativeSecurity;
|
2008-11-14 10:40:49 +03:00
|
|
|
|
|
2009-06-23 13:04:10 +04:00
|
|
|
|
internal MethodBuilder(TypeBuilder typeBuilder, string name, MethodAttributes attributes, CallingConventions callingConvention)
|
2008-11-14 10:40:49 +03:00
|
|
|
|
{
|
|
|
|
|
this.typeBuilder = typeBuilder;
|
|
|
|
|
this.name = name;
|
|
|
|
|
this.pseudoToken = typeBuilder.ModuleBuilder.AllocPseudoToken();
|
|
|
|
|
this.nameIndex = typeBuilder.ModuleBuilder.Strings.Add(name);
|
|
|
|
|
this.attributes = attributes;
|
|
|
|
|
if ((attributes & MethodAttributes.Static) == 0)
|
|
|
|
|
{
|
|
|
|
|
callingConvention |= CallingConventions.HasThis;
|
|
|
|
|
}
|
2009-06-23 13:04:10 +04:00
|
|
|
|
this.callingConvention = callingConvention;
|
2008-11-14 10:40:49 +03:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
internal static Type[] Copy(Type[] array)
|
|
|
|
|
{
|
|
|
|
|
if (array == null || array.Length == 0)
|
|
|
|
|
{
|
|
|
|
|
return Type.EmptyTypes;
|
|
|
|
|
}
|
|
|
|
|
Type[] newArray = new Type[array.Length];
|
|
|
|
|
Array.Copy(array, newArray, array.Length);
|
|
|
|
|
return newArray;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private static Type[][] PackCustomModifiers(Type[] returnTypeCustomModifiers, Type[][] parameterTypeCustomModifiers, int parameterCount)
|
|
|
|
|
{
|
|
|
|
|
if (returnTypeCustomModifiers == null && parameterTypeCustomModifiers == null)
|
|
|
|
|
{
|
|
|
|
|
return null;
|
|
|
|
|
}
|
|
|
|
|
Type[][] newArray = new Type[parameterCount + 1][];
|
|
|
|
|
newArray[parameterCount] = Copy(returnTypeCustomModifiers);
|
|
|
|
|
if (parameterTypeCustomModifiers != null)
|
|
|
|
|
{
|
|
|
|
|
for (int i = 0; i < parameterCount; i++)
|
|
|
|
|
{
|
|
|
|
|
newArray[i] = Copy(parameterTypeCustomModifiers[i]);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
for (int i = 0; i < parameterCount; i++)
|
|
|
|
|
{
|
|
|
|
|
newArray[i] = Type.EmptyTypes;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return newArray;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public ILGenerator GetILGenerator()
|
|
|
|
|
{
|
|
|
|
|
if (ilgen == null)
|
|
|
|
|
{
|
|
|
|
|
ilgen = new ILGenerator(typeBuilder.ModuleBuilder);
|
|
|
|
|
}
|
|
|
|
|
return ilgen;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public void SetCustomAttribute(ConstructorInfo con, byte[] binaryAttribute)
|
|
|
|
|
{
|
|
|
|
|
SetCustomAttribute(new CustomAttributeBuilder(con, binaryAttribute));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private void SetDllImportPseudoCustomAttribute(CustomAttributeBuilder customBuilder)
|
|
|
|
|
{
|
|
|
|
|
if (customBuilder.IsBlob)
|
|
|
|
|
{
|
|
|
|
|
throw new NotImplementedException();
|
|
|
|
|
}
|
|
|
|
|
const short NoMangle = 0x0001;
|
|
|
|
|
const short CharSetMask = 0x0006;
|
|
|
|
|
const short CharSetNotSpec = 0x0000;
|
|
|
|
|
const short CharSetAnsi = 0x0002;
|
|
|
|
|
const short CharSetUnicode = 0x0004;
|
|
|
|
|
const short CharSetAuto = 0x0006;
|
|
|
|
|
const short SupportsLastError = 0x0040;
|
|
|
|
|
const short CallConvMask = 0x0700;
|
|
|
|
|
const short CallConvWinapi = 0x0100;
|
|
|
|
|
const short CallConvCdecl = 0x0200;
|
|
|
|
|
const short CallConvStdcall = 0x0300;
|
|
|
|
|
const short CallConvThiscall = 0x0400;
|
|
|
|
|
const short CallConvFastcall = 0x0500;
|
|
|
|
|
// non-standard flags
|
|
|
|
|
const short BestFitOn = 0x0010;
|
|
|
|
|
const short BestFitOff = 0x0020;
|
|
|
|
|
const short CharMapErrorOn = 0x1000;
|
|
|
|
|
const short CharMapErrorOff = 0x2000;
|
|
|
|
|
int name = this.nameIndex;
|
|
|
|
|
short flags = CharSetNotSpec | CallConvWinapi;
|
|
|
|
|
bool? bestFitMapping = (bool?)customBuilder.GetFieldValue("BestFitMapping");
|
|
|
|
|
if (bestFitMapping.HasValue)
|
|
|
|
|
{
|
|
|
|
|
flags |= bestFitMapping.Value ? BestFitOn : BestFitOff;
|
|
|
|
|
}
|
|
|
|
|
bool? throwOnUnmappableChar = (bool?)customBuilder.GetFieldValue("ThrowOnUnmappableChar");
|
|
|
|
|
if (throwOnUnmappableChar.HasValue)
|
|
|
|
|
{
|
|
|
|
|
flags |= throwOnUnmappableChar.Value ? CharMapErrorOn : CharMapErrorOff;
|
|
|
|
|
}
|
|
|
|
|
CallingConvention? callingConvention = (CallingConvention?)customBuilder.GetFieldValue("CallingConvention");
|
|
|
|
|
if (callingConvention.HasValue)
|
|
|
|
|
{
|
|
|
|
|
flags &= ~CallConvMask;
|
|
|
|
|
switch (callingConvention.Value)
|
|
|
|
|
{
|
|
|
|
|
case System.Runtime.InteropServices.CallingConvention.Cdecl:
|
|
|
|
|
flags |= CallConvCdecl;
|
|
|
|
|
break;
|
|
|
|
|
case System.Runtime.InteropServices.CallingConvention.FastCall:
|
|
|
|
|
flags |= CallConvFastcall;
|
|
|
|
|
break;
|
|
|
|
|
case System.Runtime.InteropServices.CallingConvention.StdCall:
|
|
|
|
|
flags |= CallConvStdcall;
|
|
|
|
|
break;
|
|
|
|
|
case System.Runtime.InteropServices.CallingConvention.ThisCall:
|
|
|
|
|
flags |= CallConvThiscall;
|
|
|
|
|
break;
|
|
|
|
|
case System.Runtime.InteropServices.CallingConvention.Winapi:
|
|
|
|
|
flags |= CallConvWinapi;
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
CharSet? charSet = (CharSet?)customBuilder.GetFieldValue("CharSet");
|
|
|
|
|
if (charSet.HasValue)
|
|
|
|
|
{
|
|
|
|
|
flags &= ~CharSetMask;
|
|
|
|
|
switch (charSet.Value)
|
|
|
|
|
{
|
|
|
|
|
case CharSet.Ansi:
|
|
|
|
|
case CharSet.None:
|
|
|
|
|
flags |= CharSetAnsi;
|
|
|
|
|
break;
|
|
|
|
|
case CharSet.Auto:
|
|
|
|
|
flags |= CharSetAuto;
|
|
|
|
|
break;
|
|
|
|
|
case CharSet.Unicode:
|
|
|
|
|
flags |= CharSetUnicode;
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
string entryPoint = (string)customBuilder.GetFieldValue("EntryPoint");
|
|
|
|
|
if (entryPoint != null)
|
|
|
|
|
{
|
|
|
|
|
name = this.ModuleBuilder.Strings.Add(entryPoint);
|
|
|
|
|
}
|
|
|
|
|
bool? exactSpelling = (bool?)customBuilder.GetFieldValue("ExactSpelling");
|
|
|
|
|
if (exactSpelling.HasValue && exactSpelling.Value)
|
|
|
|
|
{
|
|
|
|
|
flags |= NoMangle;
|
|
|
|
|
}
|
|
|
|
|
bool? preserveSig = (bool?)customBuilder.GetFieldValue("PreserveSig");
|
|
|
|
|
if (!preserveSig.HasValue || preserveSig.Value)
|
|
|
|
|
{
|
|
|
|
|
implFlags |= MethodImplAttributes.PreserveSig;
|
|
|
|
|
}
|
|
|
|
|
bool? setLastError = (bool?)customBuilder.GetFieldValue("SetLastError");
|
|
|
|
|
if (setLastError.HasValue && setLastError.Value)
|
|
|
|
|
{
|
|
|
|
|
flags |= SupportsLastError;
|
|
|
|
|
}
|
|
|
|
|
TableHeap.ImplMapTable.Record rec = new TableHeap.ImplMapTable.Record();
|
|
|
|
|
rec.MappingFlags = flags;
|
|
|
|
|
rec.MemberForwarded = pseudoToken;
|
|
|
|
|
rec.ImportName = name;
|
|
|
|
|
rec.ImportScope = this.ModuleBuilder.Tables.ModuleRef.Add(this.ModuleBuilder.Strings.Add((string)customBuilder.GetConstructorArgument(0)));
|
|
|
|
|
this.ModuleBuilder.Tables.ImplMap.AddRecord(rec);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private void SetMethodImplAttribute(CustomAttributeBuilder customBuilder)
|
|
|
|
|
{
|
|
|
|
|
MethodImplOptions opt;
|
|
|
|
|
switch (customBuilder.Constructor.GetParameters().Length)
|
|
|
|
|
{
|
|
|
|
|
case 0:
|
|
|
|
|
opt = 0;
|
|
|
|
|
break;
|
|
|
|
|
case 1:
|
|
|
|
|
{
|
|
|
|
|
object val = customBuilder.GetConstructorArgument(0);
|
|
|
|
|
if (val is short)
|
|
|
|
|
{
|
|
|
|
|
opt = (MethodImplOptions)(short)val;
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
opt = (MethodImplOptions)val;
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
default:
|
|
|
|
|
throw new NotSupportedException();
|
|
|
|
|
}
|
|
|
|
|
MethodCodeType? type = (MethodCodeType?)customBuilder.GetFieldValue("MethodCodeType");
|
|
|
|
|
implFlags = (MethodImplAttributes)opt;
|
|
|
|
|
if (type.HasValue)
|
|
|
|
|
{
|
|
|
|
|
implFlags |= (MethodImplAttributes)type;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public void SetCustomAttribute(CustomAttributeBuilder customBuilder)
|
|
|
|
|
{
|
2009-06-25 12:58:31 +04:00
|
|
|
|
Type type = customBuilder.Constructor.DeclaringType;
|
|
|
|
|
if (type == typeof(DllImportAttribute))
|
2008-11-14 10:40:49 +03:00
|
|
|
|
{
|
|
|
|
|
SetDllImportPseudoCustomAttribute(customBuilder);
|
|
|
|
|
}
|
2009-06-25 12:58:31 +04:00
|
|
|
|
else if (type == typeof(MethodImplAttribute))
|
2008-11-14 10:40:49 +03:00
|
|
|
|
{
|
|
|
|
|
SetMethodImplAttribute(customBuilder);
|
|
|
|
|
}
|
2009-06-25 12:58:31 +04:00
|
|
|
|
else if (type == typeof(PreserveSigAttribute))
|
2008-11-14 10:40:49 +03:00
|
|
|
|
{
|
|
|
|
|
implFlags |= MethodImplAttributes.PreserveSig;
|
|
|
|
|
}
|
2009-06-25 12:58:31 +04:00
|
|
|
|
else if (type == typeof(SpecialNameAttribute))
|
2008-11-25 08:07:05 +03:00
|
|
|
|
{
|
|
|
|
|
attributes |= MethodAttributes.SpecialName;
|
|
|
|
|
}
|
2008-11-14 10:40:49 +03:00
|
|
|
|
else
|
|
|
|
|
{
|
2009-06-25 12:58:31 +04:00
|
|
|
|
if (type == typeof(System.Security.SuppressUnmanagedCodeSecurityAttribute))
|
|
|
|
|
{
|
|
|
|
|
attributes |= MethodAttributes.HasSecurity;
|
|
|
|
|
}
|
2008-11-14 10:40:49 +03:00
|
|
|
|
this.ModuleBuilder.SetCustomAttribute(pseudoToken, customBuilder);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2009-11-09 09:38:30 +03:00
|
|
|
|
public void __AddDeclarativeSecurity(CustomAttributeBuilder customBuilder)
|
|
|
|
|
{
|
|
|
|
|
attributes |= MethodAttributes.HasSecurity;
|
|
|
|
|
if (declarativeSecurity == null)
|
|
|
|
|
{
|
|
|
|
|
declarativeSecurity = new List<CustomAttributeBuilder>();
|
|
|
|
|
}
|
|
|
|
|
declarativeSecurity.Add(customBuilder);
|
|
|
|
|
}
|
|
|
|
|
|
2008-11-14 10:40:49 +03:00
|
|
|
|
public void AddDeclarativeSecurity(System.Security.Permissions.SecurityAction securityAction, System.Security.PermissionSet permissionSet)
|
|
|
|
|
{
|
2009-05-17 09:59:24 +04:00
|
|
|
|
this.ModuleBuilder.AddDeclaritiveSecurity(pseudoToken, securityAction, permissionSet);
|
2008-11-14 10:40:49 +03:00
|
|
|
|
this.attributes |= MethodAttributes.HasSecurity;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public void SetImplementationFlags(MethodImplAttributes attributes)
|
|
|
|
|
{
|
|
|
|
|
implFlags = attributes;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public ParameterBuilder DefineParameter(int position, ParameterAttributes attributes, string strParamName)
|
|
|
|
|
{
|
|
|
|
|
if (parameters == null)
|
|
|
|
|
{
|
|
|
|
|
parameters = new List<ParameterBuilder>();
|
|
|
|
|
}
|
|
|
|
|
this.ModuleBuilder.Tables.Param.AddRow();
|
|
|
|
|
ParameterBuilder pb = new ParameterBuilder(this.ModuleBuilder, position, attributes, strParamName);
|
|
|
|
|
parameters.Add(pb);
|
|
|
|
|
return pb;
|
|
|
|
|
}
|
|
|
|
|
|
2009-06-23 13:04:10 +04:00
|
|
|
|
public void SetSignature(Type returnType, Type[] returnTypeRequiredCustomModifiers, Type[] returnTypeOptionalCustomModifiers, Type[] parameterTypes, Type[][] parameterTypeRequiredCustomModifiers, Type[][] parameterTypeOptionalCustomModifiers)
|
|
|
|
|
{
|
|
|
|
|
this.returnType = returnType ?? typeof(void);
|
|
|
|
|
this.parameterTypes = Copy(parameterTypes);
|
|
|
|
|
this.requiredCustomModifiers = PackCustomModifiers(returnTypeRequiredCustomModifiers, parameterTypeRequiredCustomModifiers, this.parameterTypes.Length);
|
|
|
|
|
this.optionalCustomModifiers = PackCustomModifiers(returnTypeOptionalCustomModifiers, parameterTypeOptionalCustomModifiers, this.parameterTypes.Length);
|
|
|
|
|
}
|
|
|
|
|
|
2009-06-23 13:06:51 +04:00
|
|
|
|
public GenericTypeParameterBuilder[] DefineGenericParameters(params string[] names)
|
|
|
|
|
{
|
|
|
|
|
gtpb = new GenericTypeParameterBuilder[names.Length];
|
|
|
|
|
for (int i = 0; i < names.Length; i++)
|
|
|
|
|
{
|
|
|
|
|
TableHeap.GenericParamTable.Record rec = new TableHeap.GenericParamTable.Record();
|
|
|
|
|
rec.Number = (short)i;
|
|
|
|
|
rec.Flags = 0;
|
|
|
|
|
rec.Owner = pseudoToken;
|
|
|
|
|
rec.Name = this.ModuleBuilder.Strings.Add(names[i]);
|
|
|
|
|
gtpb[i] = new GenericTypeParameterBuilder(this.ModuleBuilder, names[i], null, this, this.ModuleBuilder.Tables.GenericParam.AddRecord(rec), i);
|
|
|
|
|
}
|
|
|
|
|
return (GenericTypeParameterBuilder[])gtpb.Clone();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public override MethodInfo MakeGenericMethod(params Type[] typeArguments)
|
|
|
|
|
{
|
|
|
|
|
return new GenericMethodInstance(this, typeArguments);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public override Type[] GetGenericArguments()
|
|
|
|
|
{
|
|
|
|
|
return gtpb == null ? Type.EmptyTypes : (Type[])gtpb.Clone();
|
|
|
|
|
}
|
|
|
|
|
|
2008-11-14 10:40:49 +03:00
|
|
|
|
public override MethodInfo GetBaseDefinition()
|
|
|
|
|
{
|
|
|
|
|
throw new NotSupportedException();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public override Type ReturnType
|
|
|
|
|
{
|
|
|
|
|
get { return returnType; }
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public override ParameterInfo ReturnParameter
|
|
|
|
|
{
|
|
|
|
|
get { return new ParameterInfoImpl(this, -1); }
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public override ICustomAttributeProvider ReturnTypeCustomAttributes
|
|
|
|
|
{
|
|
|
|
|
get { throw new NotImplementedException(); }
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public override MethodAttributes Attributes
|
|
|
|
|
{
|
|
|
|
|
get { return attributes; }
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public override MethodImplAttributes GetMethodImplementationFlags()
|
|
|
|
|
{
|
|
|
|
|
return implFlags;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private class ParameterInfoImpl : ParameterInfo
|
|
|
|
|
{
|
|
|
|
|
private readonly MethodBuilder method;
|
|
|
|
|
private readonly int parameter;
|
|
|
|
|
|
|
|
|
|
internal ParameterInfoImpl(MethodBuilder method, int parameter)
|
|
|
|
|
{
|
|
|
|
|
this.method = method;
|
|
|
|
|
this.parameter = parameter;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public override Type ParameterType
|
|
|
|
|
{
|
|
|
|
|
get
|
|
|
|
|
{
|
|
|
|
|
return parameter == -1 ? method.returnType : method.parameterTypes[parameter];
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public override Type[] GetOptionalCustomModifiers()
|
|
|
|
|
{
|
|
|
|
|
if (method.optionalCustomModifiers == null)
|
|
|
|
|
{
|
|
|
|
|
return Type.EmptyTypes;
|
|
|
|
|
}
|
|
|
|
|
int index = parameter == -1 ? method.optionalCustomModifiers.Length - 1 : parameter;
|
|
|
|
|
return Copy(method.optionalCustomModifiers[index]);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public override Type[] GetRequiredCustomModifiers()
|
|
|
|
|
{
|
|
|
|
|
if (method.requiredCustomModifiers == null)
|
|
|
|
|
{
|
|
|
|
|
return Type.EmptyTypes;
|
|
|
|
|
}
|
|
|
|
|
int index = parameter == -1 ? method.requiredCustomModifiers.Length - 1 : parameter;
|
|
|
|
|
return Copy(method.requiredCustomModifiers[index]);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public override ParameterInfo[] GetParameters()
|
|
|
|
|
{
|
|
|
|
|
ParameterInfo[] parameters = new ParameterInfo[parameterTypes.Length];
|
|
|
|
|
for (int i = 0; i < parameters.Length; i++)
|
|
|
|
|
{
|
|
|
|
|
parameters[i] = new ParameterInfoImpl(this, i);
|
|
|
|
|
}
|
|
|
|
|
return parameters;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public override object Invoke(object obj, BindingFlags invokeAttr, Binder binder, object[] parameters, System.Globalization.CultureInfo culture)
|
|
|
|
|
{
|
|
|
|
|
throw new NotImplementedException();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public override RuntimeMethodHandle MethodHandle
|
|
|
|
|
{
|
|
|
|
|
get { throw new NotImplementedException(); }
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public override Type DeclaringType
|
|
|
|
|
{
|
|
|
|
|
get { return this.ModuleBuilder.IsModuleType(typeBuilder) ? null : typeBuilder; }
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public override object[] GetCustomAttributes(Type attributeType, bool inherit)
|
|
|
|
|
{
|
|
|
|
|
throw new NotImplementedException();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public override object[] GetCustomAttributes(bool inherit)
|
|
|
|
|
{
|
|
|
|
|
throw new NotImplementedException();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public override bool IsDefined(Type attributeType, bool inherit)
|
|
|
|
|
{
|
|
|
|
|
throw new NotImplementedException();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public override string Name
|
|
|
|
|
{
|
|
|
|
|
get { return name; }
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public override Type ReflectedType
|
|
|
|
|
{
|
|
|
|
|
get { return this.DeclaringType; }
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public override CallingConventions CallingConvention
|
|
|
|
|
{
|
|
|
|
|
get { throw new NotImplementedException(); }
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public override int MetadataToken
|
|
|
|
|
{
|
|
|
|
|
get { return pseudoToken; }
|
|
|
|
|
}
|
|
|
|
|
|
2009-06-23 13:06:51 +04:00
|
|
|
|
public override bool IsGenericMethod
|
|
|
|
|
{
|
|
|
|
|
get { return gtpb != null; }
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public override bool IsGenericMethodDefinition
|
|
|
|
|
{
|
|
|
|
|
get { return gtpb != null; }
|
|
|
|
|
}
|
|
|
|
|
|
2009-05-25 17:42:15 +04:00
|
|
|
|
#if NET_4_0
|
|
|
|
|
public override Module Module
|
|
|
|
|
{
|
|
|
|
|
get { return typeBuilder.Module; }
|
|
|
|
|
}
|
|
|
|
|
#endif
|
|
|
|
|
|
2008-11-14 10:40:49 +03:00
|
|
|
|
internal void Bake()
|
|
|
|
|
{
|
2009-06-23 13:04:10 +04:00
|
|
|
|
ByteBuffer signature = new ByteBuffer(16);
|
2009-06-23 13:06:51 +04:00
|
|
|
|
SignatureHelper.WriteMethodSig(this.ModuleBuilder, signature, callingConvention, returnType, parameterTypes, requiredCustomModifiers, optionalCustomModifiers, gtpb == null ? 0 : gtpb.Length);
|
2009-06-23 13:04:10 +04:00
|
|
|
|
this.signature = this.ModuleBuilder.Blobs.Add(signature);
|
|
|
|
|
|
2008-11-14 10:40:49 +03:00
|
|
|
|
if (ilgen != null)
|
|
|
|
|
{
|
|
|
|
|
if (this.ModuleBuilder.symbolWriter != null)
|
|
|
|
|
{
|
|
|
|
|
this.ModuleBuilder.symbolWriter.OpenMethod(new SymbolToken(-pseudoToken | 0x06000000));
|
|
|
|
|
}
|
|
|
|
|
rva = ilgen.WriteBody();
|
|
|
|
|
if (this.ModuleBuilder.symbolWriter != null)
|
|
|
|
|
{
|
|
|
|
|
this.ModuleBuilder.symbolWriter.CloseMethod();
|
|
|
|
|
}
|
|
|
|
|
ilgen = null;
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
rva = -1;
|
|
|
|
|
}
|
2009-11-09 09:38:30 +03:00
|
|
|
|
|
|
|
|
|
if (declarativeSecurity != null)
|
|
|
|
|
{
|
|
|
|
|
this.ModuleBuilder.AddDeclarativeSecurity(pseudoToken, declarativeSecurity);
|
|
|
|
|
}
|
2008-11-14 10:40:49 +03:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
internal ModuleBuilder ModuleBuilder
|
|
|
|
|
{
|
|
|
|
|
get { return typeBuilder.ModuleBuilder; }
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
internal void WriteMethodDefRecord(int baseRVA, MetadataWriter mw, ref int paramList)
|
|
|
|
|
{
|
|
|
|
|
if (rva != -1)
|
|
|
|
|
{
|
|
|
|
|
mw.Write(rva + baseRVA);
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
mw.Write(0);
|
|
|
|
|
}
|
|
|
|
|
mw.Write((short)implFlags);
|
|
|
|
|
mw.Write((short)attributes);
|
|
|
|
|
mw.WriteStringIndex(nameIndex);
|
|
|
|
|
mw.WriteBlobIndex(signature);
|
|
|
|
|
mw.WriteParam(paramList);
|
|
|
|
|
if (parameters != null)
|
|
|
|
|
{
|
|
|
|
|
paramList += parameters.Count;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
internal void WriteParamRecords(MetadataWriter mw)
|
|
|
|
|
{
|
|
|
|
|
if (parameters != null)
|
|
|
|
|
{
|
|
|
|
|
foreach (ParameterBuilder pb in parameters)
|
|
|
|
|
{
|
|
|
|
|
pb.WriteParamRecord(mw);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
internal void FixupToken(int token, ref int parameterToken)
|
|
|
|
|
{
|
|
|
|
|
typeBuilder.ModuleBuilder.RegisterTokenFixup(this.pseudoToken, token);
|
|
|
|
|
if (parameters != null)
|
|
|
|
|
{
|
|
|
|
|
foreach (ParameterBuilder pb in parameters)
|
|
|
|
|
{
|
|
|
|
|
pb.FixupToken(parameterToken++);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
internal bool MatchParameters(Type[] types)
|
|
|
|
|
{
|
|
|
|
|
if (types.Length == parameterTypes.Length)
|
|
|
|
|
{
|
|
|
|
|
for (int i = 0; i < types.Length; i++)
|
|
|
|
|
{
|
|
|
|
|
if (!types[i].Equals(parameterTypes[i]))
|
|
|
|
|
{
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
}
|
2009-06-22 11:01:29 +04:00
|
|
|
|
|
|
|
|
|
interface IMethodInstance
|
|
|
|
|
{
|
|
|
|
|
MethodBase GetMethodOnTypeDefinition();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
sealed class MethodInstance : MethodInfo, IMethodInstance
|
|
|
|
|
{
|
|
|
|
|
private readonly Type type;
|
|
|
|
|
private readonly MethodInfo method;
|
|
|
|
|
|
|
|
|
|
internal MethodInstance(Type type, MethodInfo method)
|
|
|
|
|
{
|
|
|
|
|
Debug.Assert(method.DeclaringType.IsGenericTypeDefinition);
|
|
|
|
|
this.type = type;
|
|
|
|
|
this.method = method;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public override bool Equals(object obj)
|
|
|
|
|
{
|
|
|
|
|
MethodInstance other = obj as MethodInstance;
|
|
|
|
|
return other != null && other.type == type && other.method == method;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public override int GetHashCode()
|
|
|
|
|
{
|
|
|
|
|
return type.GetHashCode() * 23 + method.GetHashCode();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public override MethodAttributes Attributes
|
|
|
|
|
{
|
|
|
|
|
get { return method.Attributes; }
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public override MethodImplAttributes GetMethodImplementationFlags()
|
|
|
|
|
{
|
|
|
|
|
throw new NotImplementedException();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public override ParameterInfo[] GetParameters()
|
|
|
|
|
{
|
|
|
|
|
return ReplaceGenericParameters(type, method.GetParameters());
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public override ParameterInfo ReturnParameter
|
|
|
|
|
{
|
|
|
|
|
get { return ReplaceGenericParameter(type, method.ReturnParameter); }
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public override Type ReturnType
|
|
|
|
|
{
|
|
|
|
|
get { return FieldInstance.ReplaceGenericParameter(type, method.ReturnType); }
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public override object Invoke(object obj, BindingFlags invokeAttr, Binder binder, object[] parameters, System.Globalization.CultureInfo culture)
|
|
|
|
|
{
|
|
|
|
|
throw new NotImplementedException();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public override RuntimeMethodHandle MethodHandle
|
|
|
|
|
{
|
|
|
|
|
get { throw new NotImplementedException(); }
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public override Type DeclaringType
|
|
|
|
|
{
|
|
|
|
|
get { return type; }
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public override object[] GetCustomAttributes(Type attributeType, bool inherit)
|
|
|
|
|
{
|
|
|
|
|
throw new NotImplementedException();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public override object[] GetCustomAttributes(bool inherit)
|
|
|
|
|
{
|
|
|
|
|
throw new NotImplementedException();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public override bool IsDefined(Type attributeType, bool inherit)
|
|
|
|
|
{
|
|
|
|
|
throw new NotImplementedException();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public override string Name
|
|
|
|
|
{
|
|
|
|
|
get { return method.Name; }
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public override Type ReflectedType
|
|
|
|
|
{
|
|
|
|
|
get { return type; }
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public override MethodInfo GetBaseDefinition()
|
|
|
|
|
{
|
|
|
|
|
throw new NotImplementedException();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public override ICustomAttributeProvider ReturnTypeCustomAttributes
|
|
|
|
|
{
|
|
|
|
|
get { throw new NotImplementedException(); }
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
MethodBase IMethodInstance.GetMethodOnTypeDefinition()
|
|
|
|
|
{
|
|
|
|
|
return method;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private sealed class GenericInstanceParameterInfo : ParameterInfo
|
|
|
|
|
{
|
|
|
|
|
private readonly Type container;
|
|
|
|
|
private readonly ParameterInfo parameterInfo;
|
|
|
|
|
|
|
|
|
|
internal GenericInstanceParameterInfo(Type container, ParameterInfo parameterInfo)
|
|
|
|
|
{
|
|
|
|
|
this.container = container;
|
|
|
|
|
this.parameterInfo = parameterInfo;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public override Type ParameterType
|
|
|
|
|
{
|
|
|
|
|
get { return FieldInstance.ReplaceGenericParameter(container, parameterInfo.ParameterType); }
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public override Type[] GetOptionalCustomModifiers()
|
|
|
|
|
{
|
|
|
|
|
return FieldInstance.ReplaceGenericParameters(container, parameterInfo.GetOptionalCustomModifiers());
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public override Type[] GetRequiredCustomModifiers()
|
|
|
|
|
{
|
|
|
|
|
return FieldInstance.ReplaceGenericParameters(container, parameterInfo.GetRequiredCustomModifiers());
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private static ParameterInfo ReplaceGenericParameter(Type type, ParameterInfo parameterInfo)
|
|
|
|
|
{
|
|
|
|
|
return new GenericInstanceParameterInfo(type, parameterInfo);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
internal static ParameterInfo[] ReplaceGenericParameters(Type type, ParameterInfo[] parameterInfo)
|
|
|
|
|
{
|
|
|
|
|
ParameterInfo[] newArray = new ParameterInfo[parameterInfo.Length];
|
|
|
|
|
for (int i = 0; i < newArray.Length; i++)
|
|
|
|
|
{
|
|
|
|
|
newArray[i] = ReplaceGenericParameter(type, parameterInfo[i]);
|
|
|
|
|
}
|
|
|
|
|
return newArray;
|
|
|
|
|
}
|
|
|
|
|
}
|
2009-06-23 13:06:51 +04:00
|
|
|
|
|
|
|
|
|
sealed class GenericMethodInstance : MethodInfo
|
|
|
|
|
{
|
|
|
|
|
private readonly MethodBuilder method;
|
|
|
|
|
private readonly Type[] args;
|
|
|
|
|
|
|
|
|
|
internal GenericMethodInstance(MethodBuilder method, Type[] args)
|
|
|
|
|
{
|
|
|
|
|
this.method = method;
|
|
|
|
|
this.args = args;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public override bool Equals(object obj)
|
|
|
|
|
{
|
|
|
|
|
GenericMethodInstance other = obj as GenericMethodInstance;
|
|
|
|
|
if (other != null && other.method == method && other.args.Length == args.Length)
|
|
|
|
|
{
|
|
|
|
|
for (int i = 0; i < args.Length; i++)
|
|
|
|
|
{
|
|
|
|
|
if (!args[i].Equals(other.args[i]))
|
|
|
|
|
{
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public override int GetHashCode()
|
|
|
|
|
{
|
|
|
|
|
int h = method.GetHashCode();
|
|
|
|
|
foreach (Type type in args)
|
|
|
|
|
{
|
|
|
|
|
h = h * 27 + type.GetHashCode();
|
|
|
|
|
}
|
|
|
|
|
return h;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public override MethodInfo GetBaseDefinition()
|
|
|
|
|
{
|
|
|
|
|
throw new NotImplementedException();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public override ICustomAttributeProvider ReturnTypeCustomAttributes
|
|
|
|
|
{
|
|
|
|
|
get { throw new NotImplementedException(); }
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public override MethodAttributes Attributes
|
|
|
|
|
{
|
|
|
|
|
get { return method.Attributes; }
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public override MethodImplAttributes GetMethodImplementationFlags()
|
|
|
|
|
{
|
|
|
|
|
throw new NotImplementedException();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private sealed class GenericInstanceParameterInfo : ParameterInfo
|
|
|
|
|
{
|
|
|
|
|
private readonly GenericMethodInstance container;
|
|
|
|
|
private readonly ParameterInfo parameterInfo;
|
|
|
|
|
|
|
|
|
|
internal GenericInstanceParameterInfo(GenericMethodInstance container, ParameterInfo parameterInfo)
|
|
|
|
|
{
|
|
|
|
|
this.container = container;
|
|
|
|
|
this.parameterInfo = parameterInfo;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public override Type ParameterType
|
|
|
|
|
{
|
|
|
|
|
get { return ReplaceGenericParameter(container, parameterInfo.ParameterType); }
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public override Type[] GetOptionalCustomModifiers()
|
|
|
|
|
{
|
|
|
|
|
return ReplaceGenericParameters(container, parameterInfo.GetOptionalCustomModifiers());
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public override Type[] GetRequiredCustomModifiers()
|
|
|
|
|
{
|
|
|
|
|
return ReplaceGenericParameters(container, parameterInfo.GetRequiredCustomModifiers());
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public override ParameterInfo[] GetParameters()
|
|
|
|
|
{
|
|
|
|
|
ParameterInfo[] param = method.GetParameters();
|
|
|
|
|
for (int i = 0; i < param.Length; i++)
|
|
|
|
|
{
|
|
|
|
|
param[i] = new GenericInstanceParameterInfo(this, param[i]);
|
|
|
|
|
}
|
|
|
|
|
return param;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public override ParameterInfo ReturnParameter
|
|
|
|
|
{
|
|
|
|
|
get { return new GenericInstanceParameterInfo(this, method.ReturnParameter); }
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public override Type ReturnType
|
|
|
|
|
{
|
|
|
|
|
get { return ReplaceGenericParameter(this, method.ReturnType); }
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public override object Invoke(object obj, BindingFlags invokeAttr, Binder binder, object[] parameters, System.Globalization.CultureInfo culture)
|
|
|
|
|
{
|
|
|
|
|
throw new NotImplementedException();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public override RuntimeMethodHandle MethodHandle
|
|
|
|
|
{
|
|
|
|
|
get { throw new NotImplementedException(); }
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public override Type DeclaringType
|
|
|
|
|
{
|
|
|
|
|
get { return method.DeclaringType; }
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public override object[] GetCustomAttributes(Type attributeType, bool inherit)
|
|
|
|
|
{
|
|
|
|
|
throw new NotImplementedException();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public override object[] GetCustomAttributes(bool inherit)
|
|
|
|
|
{
|
|
|
|
|
throw new NotImplementedException();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public override bool IsDefined(Type attributeType, bool inherit)
|
|
|
|
|
{
|
|
|
|
|
throw new NotImplementedException();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public override string Name
|
|
|
|
|
{
|
|
|
|
|
get { return method.Name; }
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public override Type ReflectedType
|
|
|
|
|
{
|
|
|
|
|
get { return this.DeclaringType; }
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public override bool IsGenericMethod
|
|
|
|
|
{
|
|
|
|
|
get { return true; }
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public override MethodInfo GetGenericMethodDefinition()
|
|
|
|
|
{
|
|
|
|
|
return method;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public override Type[] GetGenericArguments()
|
|
|
|
|
{
|
|
|
|
|
return (Type[])args.Clone();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private static Type ReplaceGenericParameter(GenericMethodInstance container, Type type)
|
|
|
|
|
{
|
|
|
|
|
if (type.IsGenericParameter && type.DeclaringMethod == container)
|
|
|
|
|
{
|
|
|
|
|
return container.args[type.GenericParameterPosition];
|
|
|
|
|
}
|
|
|
|
|
return type;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private static Type[] ReplaceGenericParameters(GenericMethodInstance container, Type[] types)
|
|
|
|
|
{
|
|
|
|
|
Type[] newarray = new Type[types.Length];
|
|
|
|
|
for (int i = 0; i < newarray.Length; i++)
|
|
|
|
|
{
|
|
|
|
|
newarray[i] = ReplaceGenericParameter(container, types[i]);
|
|
|
|
|
}
|
|
|
|
|
return newarray;
|
|
|
|
|
}
|
|
|
|
|
}
|
2008-11-14 10:40:49 +03:00
|
|
|
|
}
|