1 /*
2   Copyright (C) 2009, 2010 Jeroen Frijters
3 
4   This software is provided 'as-is', without any express or implied
5   warranty.  In no event will the authors be held liable for any damages
6   arising from the use of this software.
7 
8   Permission is granted to anyone to use this software for any purpose,
9   including commercial applications, and to alter it and redistribute it
10   freely, subject to the following restrictions:
11 
12   1. The origin of this software must not be misrepresented; you must not
13      claim that you wrote the original software. If you use this software
14      in a product, an acknowledgment in the product documentation would be
15      appreciated but is not required.
16   2. Altered source versions must be plainly marked as such, and must not be
17      misrepresented as being the original software.
18   3. This notice may not be removed or altered from any source distribution.
19 
20   Jeroen Frijters
21   jeroen@frijters.net
22 
23 */
24 using System;
25 using System.Collections.Generic;
26 using System.Text;
27 
28 namespace IKVM.Reflection
29 {
30 	// this represents both generic method instantiations and non-generic methods on generic type instantations
31 	// (this means that it can be a generic method declaration as well as a generic method instance)
32 	sealed class GenericMethodInstance : MethodInfo
33 	{
34 		private readonly Type declaringType;
35 		private readonly MethodInfo method;
36 		private readonly Type[] methodArgs;
37 		private MethodSignature lazyMethodSignature;
38 
GenericMethodInstance(Type declaringType, MethodInfo method, Type[] methodArgs)39 		internal GenericMethodInstance(Type declaringType, MethodInfo method, Type[] methodArgs)
40 		{
41 			System.Diagnostics.Debug.Assert(!(method is GenericMethodInstance));
42 			this.declaringType = declaringType;
43 			this.method = method;
44 			this.methodArgs = methodArgs;
45 		}
46 
Equals(object obj)47 		public override bool Equals(object obj)
48 		{
49 			GenericMethodInstance other = obj as GenericMethodInstance;
50 			return other != null
51 				&& other.method.Equals(method)
52 				&& other.declaringType.Equals(declaringType)
53 				&& Util.ArrayEquals(other.methodArgs, methodArgs);
54 		}
55 
GetHashCode()56 		public override int GetHashCode()
57 		{
58 			return declaringType.GetHashCode() * 33 ^ method.GetHashCode() ^ Util.GetHashCode(methodArgs);
59 		}
60 
61 		public override Type ReturnType
62 		{
63 			get { return method.ReturnType.BindTypeParameters(this); }
64 		}
65 
66 		public override ParameterInfo ReturnParameter
67 		{
68 			get { return new GenericParameterInfoImpl(this, method.ReturnParameter); }
69 		}
70 
GetParameters()71 		public override ParameterInfo[] GetParameters()
72 		{
73 			ParameterInfo[] parameters = method.GetParameters();
74 			for (int i = 0; i < parameters.Length; i++)
75 			{
76 				parameters[i] = new GenericParameterInfoImpl(this, parameters[i]);
77 			}
78 			return parameters;
79 		}
80 
81 		internal override int ParameterCount
82 		{
83 			get { return method.ParameterCount; }
84 		}
85 
86 		public override CallingConventions CallingConvention
87 		{
88 			get { return method.CallingConvention; }
89 		}
90 
91 		public override MethodAttributes Attributes
92 		{
93 			get { return method.Attributes; }
94 		}
95 
GetMethodImplementationFlags()96 		public override MethodImplAttributes GetMethodImplementationFlags()
97 		{
98 			return method.GetMethodImplementationFlags();
99 		}
100 
101 		public override string Name
102 		{
103 			get { return method.Name; }
104 		}
105 
106 		public override Type DeclaringType
107 		{
108 			get { return declaringType.IsModulePseudoType ? null : declaringType; }
109 		}
110 
111 		public override Module Module
112 		{
113 			get { return method.Module; }
114 		}
115 
116 		public override int MetadataToken
117 		{
118 			get { return method.MetadataToken; }
119 		}
120 
GetMethodBody()121 		public override MethodBody GetMethodBody()
122 		{
123 			IKVM.Reflection.Reader.MethodDefImpl md = method as IKVM.Reflection.Reader.MethodDefImpl;
124 			if (md != null)
125 			{
126 				return md.GetMethodBody(this);
127 			}
128 			throw new NotSupportedException();
129 		}
130 
131 		public override int __MethodRVA
132 		{
133 			get { return method.__MethodRVA; }
134 		}
135 
MakeGenericMethod(params Type[] typeArguments)136 		public override MethodInfo MakeGenericMethod(params Type[] typeArguments)
137 		{
138 			return new GenericMethodInstance(declaringType, method, typeArguments);
139 		}
140 
141 		public override bool IsGenericMethod
142 		{
143 			get { return method.IsGenericMethod; }
144 		}
145 
146 		public override bool IsGenericMethodDefinition
147 		{
148 			get { return method.IsGenericMethodDefinition && methodArgs == null; }
149 		}
150 
151 		public override bool ContainsGenericParameters
152 		{
153 			get
154 			{
155 				if (declaringType.ContainsGenericParameters)
156 				{
157 					return true;
158 				}
159 				if (methodArgs != null)
160 				{
161 					foreach (Type type in methodArgs)
162 					{
163 						if (type.ContainsGenericParameters)
164 						{
165 							return true;
166 						}
167 					}
168 				}
169 				return false;
170 			}
171 		}
172 
GetGenericMethodDefinition()173 		public override MethodInfo GetGenericMethodDefinition()
174 		{
175 			if (this.IsGenericMethod)
176 			{
177 				if (this.IsGenericMethodDefinition)
178 				{
179 					return this;
180 				}
181 				else if (declaringType.IsConstructedGenericType)
182 				{
183 					return new GenericMethodInstance(declaringType, method, null);
184 				}
185 				else
186 				{
187 					return method;
188 				}
189 			}
190 			throw new InvalidOperationException();
191 		}
192 
__GetMethodOnTypeDefinition()193 		public override MethodBase __GetMethodOnTypeDefinition()
194 		{
195 			return method;
196 		}
197 
GetGenericArguments()198 		public override Type[] GetGenericArguments()
199 		{
200 			if (methodArgs == null)
201 			{
202 				return method.GetGenericArguments();
203 			}
204 			else
205 			{
206 				return (Type[])methodArgs.Clone();
207 			}
208 		}
209 
GetGenericMethodArgument(int index)210 		internal override Type GetGenericMethodArgument(int index)
211 		{
212 			if (methodArgs == null)
213 			{
214 				return method.GetGenericMethodArgument(index);
215 			}
216 			else
217 			{
218 				return methodArgs[index];
219 			}
220 		}
221 
GetGenericMethodArgumentCount()222 		internal override int GetGenericMethodArgumentCount()
223 		{
224 			return method.GetGenericMethodArgumentCount();
225 		}
226 
GetMethodOnTypeDefinition()227 		internal override MethodInfo GetMethodOnTypeDefinition()
228 		{
229 			return method.GetMethodOnTypeDefinition();
230 		}
231 
ImportTo(Emit.ModuleBuilder module)232 		internal override int ImportTo(Emit.ModuleBuilder module)
233 		{
234 			if (methodArgs == null)
235 			{
236 				return module.ImportMethodOrField(declaringType, method.Name, method.MethodSignature);
237 			}
238 			else
239 			{
240 				return module.ImportMethodSpec(declaringType, method, methodArgs);
241 			}
242 		}
243 
244 		internal override MethodSignature MethodSignature
245 		{
246 			get { return lazyMethodSignature ?? (lazyMethodSignature = method.MethodSignature.Bind(declaringType, methodArgs)); }
247 		}
248 
BindTypeParameters(Type type)249 		internal override MethodBase BindTypeParameters(Type type)
250 		{
251 			System.Diagnostics.Debug.Assert(methodArgs == null);
252 			return new GenericMethodInstance(declaringType.BindTypeParameters(type), method, null);
253 		}
254 
255 		internal override bool HasThis
256 		{
257 			get { return method.HasThis; }
258 		}
259 
__GetMethodImpls()260 		public override MethodInfo[] __GetMethodImpls()
261 		{
262 			MethodInfo[] methods = method.__GetMethodImpls();
263 			for (int i = 0; i < methods.Length; i++)
264 			{
265 				methods[i] = (MethodInfo)methods[i].BindTypeParameters(declaringType);
266 			}
267 			return methods;
268 		}
269 
GetCurrentToken()270 		internal override int GetCurrentToken()
271 		{
272 			return method.GetCurrentToken();
273 		}
274 
275 		internal override bool IsBaked
276 		{
277 			get { return method.IsBaked; }
278 		}
279 	}
280 
281 	sealed class GenericFieldInstance : FieldInfo
282 	{
283 		private readonly Type declaringType;
284 		private readonly FieldInfo field;
285 
GenericFieldInstance(Type declaringType, FieldInfo field)286 		internal GenericFieldInstance(Type declaringType, FieldInfo field)
287 		{
288 			this.declaringType = declaringType;
289 			this.field = field;
290 		}
291 
Equals(object obj)292 		public override bool Equals(object obj)
293 		{
294 			GenericFieldInstance other = obj as GenericFieldInstance;
295 			return other != null && other.declaringType.Equals(declaringType) && other.field.Equals(field);
296 		}
297 
GetHashCode()298 		public override int GetHashCode()
299 		{
300 			return declaringType.GetHashCode() * 3 ^ field.GetHashCode();
301 		}
302 
303 		public override FieldAttributes Attributes
304 		{
305 			get { return field.Attributes; }
306 		}
307 
308 		public override string Name
309 		{
310 			get { return field.Name; }
311 		}
312 
313 		public override Type DeclaringType
314 		{
315 			get { return declaringType; }
316 		}
317 
318 		public override Module Module
319 		{
320 			get { return declaringType.Module; }
321 		}
322 
323 		public override int MetadataToken
324 		{
325 			get { return field.MetadataToken; }
326 		}
327 
GetRawConstantValue()328 		public override object GetRawConstantValue()
329 		{
330 			return field.GetRawConstantValue();
331 		}
332 
__GetDataFromRVA(byte[] data, int offset, int length)333 		public override void __GetDataFromRVA(byte[] data, int offset, int length)
334 		{
335 			field.__GetDataFromRVA(data, offset, length);
336 		}
337 
338 		public override int __FieldRVA
339 		{
340 			get { return field.__FieldRVA; }
341 		}
342 
__TryGetFieldOffset(out int offset)343 		public override bool __TryGetFieldOffset(out int offset)
344 		{
345 			return field.__TryGetFieldOffset(out offset);
346 		}
347 
__GetFieldOnTypeDefinition()348 		public override FieldInfo __GetFieldOnTypeDefinition()
349 		{
350 			return field;
351 		}
352 
353 		internal override FieldSignature FieldSignature
354 		{
355 			get { return field.FieldSignature.ExpandTypeParameters(declaringType); }
356 		}
357 
ImportTo(Emit.ModuleBuilder module)358 		internal override int ImportTo(Emit.ModuleBuilder module)
359 		{
360 			return module.ImportMethodOrField(declaringType, field.Name, field.FieldSignature);
361 		}
362 
BindTypeParameters(Type type)363 		internal override FieldInfo BindTypeParameters(Type type)
364 		{
365 			return new GenericFieldInstance(declaringType.BindTypeParameters(type), field);
366 		}
367 
GetCurrentToken()368 		internal override int GetCurrentToken()
369 		{
370 			return field.GetCurrentToken();
371 		}
372 
373 		internal override bool IsBaked
374 		{
375 			get { return field.IsBaked; }
376 		}
377 	}
378 
379 	sealed class GenericParameterInfoImpl : ParameterInfo
380 	{
381 		private readonly GenericMethodInstance method;
382 		private readonly ParameterInfo parameterInfo;
383 
GenericParameterInfoImpl(GenericMethodInstance method, ParameterInfo parameterInfo)384 		internal GenericParameterInfoImpl(GenericMethodInstance method, ParameterInfo parameterInfo)
385 		{
386 			this.method = method;
387 			this.parameterInfo = parameterInfo;
388 		}
389 
390 		public override string Name
391 		{
392 			get { return parameterInfo.Name; }
393 		}
394 
395 		public override Type ParameterType
396 		{
397 			get { return parameterInfo.ParameterType.BindTypeParameters(method); }
398 		}
399 
400 		public override ParameterAttributes Attributes
401 		{
402 			get { return parameterInfo.Attributes; }
403 		}
404 
405 		public override int Position
406 		{
407 			get { return parameterInfo.Position; }
408 		}
409 
410 		public override object RawDefaultValue
411 		{
412 			get { return parameterInfo.RawDefaultValue; }
413 		}
414 
__GetCustomModifiers()415 		public override CustomModifiers __GetCustomModifiers()
416 		{
417 			return parameterInfo.__GetCustomModifiers().Bind(method);
418 		}
419 
__TryGetFieldMarshal(out FieldMarshal fieldMarshal)420 		public override bool __TryGetFieldMarshal(out FieldMarshal fieldMarshal)
421 		{
422 			return parameterInfo.__TryGetFieldMarshal(out fieldMarshal);
423 		}
424 
425 		public override MemberInfo Member
426 		{
427 			get { return method; }
428 		}
429 
430 		public override int MetadataToken
431 		{
432 			get { return parameterInfo.MetadataToken; }
433 		}
434 
435 		internal override Module Module
436 		{
437 			get { return method.Module; }
438 		}
439 	}
440 
441 	sealed class GenericPropertyInfo : PropertyInfo
442 	{
443 		private readonly Type typeInstance;
444 		private readonly PropertyInfo property;
445 
GenericPropertyInfo(Type typeInstance, PropertyInfo property)446 		internal GenericPropertyInfo(Type typeInstance, PropertyInfo property)
447 		{
448 			this.typeInstance = typeInstance;
449 			this.property = property;
450 		}
451 
Equals(object obj)452 		public override bool Equals(object obj)
453 		{
454 			GenericPropertyInfo other = obj as GenericPropertyInfo;
455 			return other != null && other.typeInstance == typeInstance && other.property == property;
456 		}
457 
GetHashCode()458 		public override int GetHashCode()
459 		{
460 			return typeInstance.GetHashCode() * 537 + property.GetHashCode();
461 		}
462 
463 		public override PropertyAttributes Attributes
464 		{
465 			get { return property.Attributes; }
466 		}
467 
468 		public override bool CanRead
469 		{
470 			get { return property.CanRead; }
471 		}
472 
473 		public override bool CanWrite
474 		{
475 			get { return property.CanWrite; }
476 		}
477 
Wrap(MethodInfo method)478 		private MethodInfo Wrap(MethodInfo method)
479 		{
480 			if (method == null)
481 			{
482 				return null;
483 			}
484 			return new GenericMethodInstance(typeInstance, method, null);
485 		}
486 
GetGetMethod(bool nonPublic)487 		public override MethodInfo GetGetMethod(bool nonPublic)
488 		{
489 			return Wrap(property.GetGetMethod(nonPublic));
490 		}
491 
GetSetMethod(bool nonPublic)492 		public override MethodInfo GetSetMethod(bool nonPublic)
493 		{
494 			return Wrap(property.GetSetMethod(nonPublic));
495 		}
496 
GetAccessors(bool nonPublic)497 		public override MethodInfo[] GetAccessors(bool nonPublic)
498 		{
499 			MethodInfo[] accessors = property.GetAccessors(nonPublic);
500 			for (int i = 0; i < accessors.Length; i++)
501 			{
502 				accessors[i] = Wrap(accessors[i]);
503 			}
504 			return accessors;
505 		}
506 
GetRawConstantValue()507 		public override object GetRawConstantValue()
508 		{
509 			return property.GetRawConstantValue();
510 		}
511 
512 		internal override bool IsPublic
513 		{
514 			get { return property.IsPublic; }
515 		}
516 
517 		internal override bool IsNonPrivate
518 		{
519 			get { return property.IsNonPrivate; }
520 		}
521 
522 		internal override bool IsStatic
523 		{
524 			get { return property.IsStatic; }
525 		}
526 
527 		internal override PropertySignature PropertySignature
528 		{
529 			get { return property.PropertySignature.ExpandTypeParameters(typeInstance); }
530 		}
531 
532 		public override string Name
533 		{
534 			get { return property.Name; }
535 		}
536 
537 		public override Type DeclaringType
538 		{
539 			get { return typeInstance; }
540 		}
541 
542 		public override Module Module
543 		{
544 			get { return typeInstance.Module; }
545 		}
546 
547 		public override int MetadataToken
548 		{
549 			get { return property.MetadataToken; }
550 		}
551 
BindTypeParameters(Type type)552 		internal override PropertyInfo BindTypeParameters(Type type)
553 		{
554 			return new GenericPropertyInfo(typeInstance.BindTypeParameters(type), property);
555 		}
556 
557 		internal override bool IsBaked
558 		{
559 			get { return property.IsBaked; }
560 		}
561 
GetCurrentToken()562 		internal override int GetCurrentToken()
563 		{
564 			return property.GetCurrentToken();
565 		}
566 	}
567 
568 	sealed class GenericEventInfo : EventInfo
569 	{
570 		private readonly Type typeInstance;
571 		private readonly EventInfo eventInfo;
572 
GenericEventInfo(Type typeInstance, EventInfo eventInfo)573 		internal GenericEventInfo(Type typeInstance, EventInfo eventInfo)
574 		{
575 			this.typeInstance = typeInstance;
576 			this.eventInfo = eventInfo;
577 		}
578 
Equals(object obj)579 		public override bool Equals(object obj)
580 		{
581 			GenericEventInfo other = obj as GenericEventInfo;
582 			return other != null && other.typeInstance == typeInstance && other.eventInfo == eventInfo;
583 		}
584 
GetHashCode()585 		public override int GetHashCode()
586 		{
587 			return typeInstance.GetHashCode() * 777 + eventInfo.GetHashCode();
588 		}
589 
590 		public override EventAttributes Attributes
591 		{
592 			get { return eventInfo.Attributes; }
593 		}
594 
Wrap(MethodInfo method)595 		private MethodInfo Wrap(MethodInfo method)
596 		{
597 			if (method == null)
598 			{
599 				return null;
600 			}
601 			return new GenericMethodInstance(typeInstance, method, null);
602 		}
603 
GetAddMethod(bool nonPublic)604 		public override MethodInfo GetAddMethod(bool nonPublic)
605 		{
606 			return Wrap(eventInfo.GetAddMethod(nonPublic));
607 		}
608 
GetRaiseMethod(bool nonPublic)609 		public override MethodInfo GetRaiseMethod(bool nonPublic)
610 		{
611 			return Wrap(eventInfo.GetRaiseMethod(nonPublic));
612 		}
613 
GetRemoveMethod(bool nonPublic)614 		public override MethodInfo GetRemoveMethod(bool nonPublic)
615 		{
616 			return Wrap(eventInfo.GetRemoveMethod(nonPublic));
617 		}
618 
GetOtherMethods(bool nonPublic)619 		public override MethodInfo[] GetOtherMethods(bool nonPublic)
620 		{
621 			MethodInfo[] others = eventInfo.GetOtherMethods(nonPublic);
622 			for (int i = 0; i < others.Length; i++)
623 			{
624 				others[i] = Wrap(others[i]);
625 			}
626 			return others;
627 		}
628 
__GetMethods()629 		public override MethodInfo[] __GetMethods()
630 		{
631 			MethodInfo[] others = eventInfo.__GetMethods();
632 			for (int i = 0; i < others.Length; i++)
633 			{
634 				others[i] = Wrap(others[i]);
635 			}
636 			return others;
637 		}
638 
639 		public override Type EventHandlerType
640 		{
641 			get { return eventInfo.EventHandlerType.BindTypeParameters(typeInstance); }
642 		}
643 
644 		public override string Name
645 		{
646 			get { return eventInfo.Name; }
647 		}
648 
649 		public override Type DeclaringType
650 		{
651 			get { return typeInstance; }
652 		}
653 
654 		public override Module Module
655 		{
656 			get { return eventInfo.Module; }
657 		}
658 
659 		public override int MetadataToken
660 		{
661 			get { return eventInfo.MetadataToken; }
662 		}
663 
BindTypeParameters(Type type)664 		internal override EventInfo BindTypeParameters(Type type)
665 		{
666 			return new GenericEventInfo(typeInstance.BindTypeParameters(type), eventInfo);
667 		}
668 
669 		internal override bool IsPublic
670 		{
671 			get { return eventInfo.IsPublic; }
672 		}
673 
674 		internal override bool IsNonPrivate
675 		{
676 			get { return eventInfo.IsNonPrivate; }
677 		}
678 
679 		internal override bool IsStatic
680 		{
681 			get { return eventInfo.IsStatic; }
682 		}
683 
684 		internal override bool IsBaked
685 		{
686 			get { return eventInfo.IsBaked; }
687 		}
688 
GetCurrentToken()689 		internal override int GetCurrentToken()
690 		{
691 			return eventInfo.GetCurrentToken();
692 		}
693 	}
694 }
695