We adopt roughly the same approach as the C# Reflection API: a
GenericMethodDefinition is a method which has no method parameters
substituted, but lives in a open or closed type with some or all
type parameters substituted. To ensure the uniqueness of the MethodInfo,
we cache by the method type arguments, and also cache generated
DeclaredConstructors/DeclaredMethods in the TypeInfo.
This also enables MakeGenericMethod, albeit in a slightly different form
than the Reflection API: MakeGenericMethod lives in MethodBase, so it's
callable from a constructor (even though in C# constructors cannot be
generic). This slight violation of the spec reduces code duplication, so
it's probably worth it.
Finally, VirtualAddress gets set when populating GenericMethods, and so
it'll work whether or not the methods get cached/generated ahead of
time.
With this patch, generic parameters in BaseType and method param/return
types are substituted correctly and deeply. Next up will be to apply the
same substitution rules to fields, properties, events, ...
GenericMethods should contain all MethodSpec-referenced methods,
including those which are non-generic methods inside generic types. This
patch adds those methods, and also implements parameter substitution for
type arguments in parameters & return types.
We use indices into the TypesByReferenceIndex table to defer type lookup
during model construction. However, this won't support fully generic
instances (which might not be in the type table at all). This patch
introduces a new TypeRef abstraction which can either represent a fixed
index or an instantiated generic type.