3using System.Reflection;
4using System.Reflection.Emit;
12 internal abstract partial class MethodAccessor
17 readonly
Type returnType;
18 readonly
Type[] parameterTypes;
28 protected MethodAccessor(
Type type,
string name,
Type returnType,
Type[] parameterTypes)
31 this.type = type ??
throw new ArgumentNullException(nameof(type));
32 this.name = name ??
throw new ArgumentNullException(nameof(name));
33 this.returnType = returnType ??
throw new ArgumentNullException(nameof(returnType));
34 this.parameterTypes = parameterTypes ??
throw new ArgumentNullException(nameof(parameterTypes));
45 protected string Name => name;
50 protected Type ReturnType => returnType;
55 protected Type[] ParameterTypes => parameterTypes;
60 protected MethodBase Method => AccessorUtil.LazyGet(
ref method, FindMethod) ??
throw new InternalException($
"Could not locate method {Name}.");
66 MethodBase FindMethod() => type.GetMembers(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Static | BindingFlags.Instance)
68 .Where(i => i.Name ==
Name)
69 .Where(i => i.IsConstructor && ReturnType == typeof(
void) || i is
MethodInfo m && m.ReturnType == ReturnType)
70 .Where(i => i.GetParameters().Select(i => i.ParameterType).SequenceEqual(ParameterTypes))
78 internal sealed class MethodAccessor<TDelegate> : MethodAccessor
79 where TDelegate : Delegate
82 public static MethodAccessor<TDelegate> LazyGet(
ref MethodAccessor<TDelegate> location,
Type type,
string name,
Type returnType, params
Type[] parameterTypes)
84 return AccessorUtil.LazyGet(
ref location, () =>
new MethodAccessor<TDelegate>(type, name, returnType, parameterTypes));
96 public MethodAccessor(
Type type,
string name,
Type returnType,
Type[] parameters) :
97 base(type, name, returnType, parameters)
105 public TDelegate Invoker => AccessorUtil.LazyGet(
ref invoker, MakeInvoker);
111 TDelegate MakeInvoker()
113#if FIRST_PASS || IMPORTER || EXPORTER
114 throw new NotImplementedException();
117 var delegateReturnType = GetDelegateReturnType(typeof(TDelegate));
118 if (Method.IsConstructor)
120 if (delegateReturnType == typeof(
void))
121 throw new InternalException(
"Delegate has no return type for constructor.");
125 if (delegateReturnType == typeof(
void) && mi.ReturnType != typeof(
void))
126 throw new InternalException(
"Delegate has no return type for method with return type.");
127 if (delegateReturnType != typeof(
void) && mi.ReturnType == typeof(
void))
128 throw new InternalException(
"Delegate has return type for method without return type.");
131 var parameters = Method.GetParameters();
134 var delegateParameterTypes = GetDelegateParameterTypes(typeof(TDelegate));
135 if ((Method.IsConstructor || Method.IsStatic) && delegateParameterTypes.Length != parameters.Length)
136 throw new InternalException(
"Delegate has wrong number of parameters for constructor or static method.");
137 else if (Method.IsConstructor ==
false && Method.IsStatic ==
false && delegateParameterTypes.Length != parameters.Length + 1)
138 throw new InternalException(
"Delegate has wrong number of parameters for instance method.");
141 var dm = DynamicMethodUtil.Create($
"__<MethodAccessor>__{Type.Name.Replace(".
", "_
")}__{Method.Name}",
Type,
false, delegateReturnType, delegateParameterTypes);
142 var il = JVM.Context.CodeEmitterFactory.Create(dm);
148 if (Method.IsStatic ==
false && Method.IsConstructor ==
false)
151 if (delegateParameterTypes[0] !=
Type)
152 il.EmitCastclass(
Type);
156 for (var i = 0; i < parameters.Length; i++)
158 var delegateParameterType = delegateParameterTypes[n];
160 if (parameters[i].ParameterType != delegateParameterType)
161 il.EmitCastclass(parameters[i].ParameterType);
164 if (Method.IsConstructor)
165 il.Emit(OpCodes.Newobj, Method);
166 else if (Method.IsStatic || Method.IsVirtual ==
false)
167 il.Emit(OpCodes.Call, Method);
169 il.Emit(OpCodes.Callvirt, Method);
172 if (delegateReturnType != typeof(
void))
173 if (Method.IsConstructor && delegateReturnType !=
Type || Method.IsConstructor ==
false && delegateReturnType != ((
MethodInfo)Method).ReturnType)
174 il.EmitCastclass(delegateReturnType);
176 il.Emit(OpCodes.Ret);
179 return (TDelegate)dm.CreateDelegate(typeof(TDelegate));
189 Type[] GetDelegateParameterTypes(
Type d)
191 if (d.BaseType != typeof(MulticastDelegate))
192 throw new ArgumentException(
"Not a delegate.", nameof(d));
194 var invoke = d.GetMethod(
"Invoke");
196 throw new ArgumentException(
"Not a delegate.", nameof(d));
198 var parameters = invoke.GetParameters();
199 var typeParameters =
new Type[parameters.Length];
200 for (
int i = 0; i < parameters.Length; i++)
201 typeParameters[i] = parameters[i].ParameterType;
203 return typeParameters;
214 if (d.BaseType != typeof(MulticastDelegate))
215 throw new ArgumentException(
"Not a delegate.", nameof(d));
217 var invoke = d.GetMethod(
"Invoke");
219 throw new ArgumentException(
"Not a delegate.", nameof(d));
221 return invoke.ReturnType;
IKVM.Reflection.Type Type
IKVM.Reflection.MethodInfo MethodInfo
IKVM.Reflection.MethodBase MethodBase
global::java.lang.invoke.LambdaForm.Name Name