context: //
  // System.Reflection.MonoGenericClass
  //
  // Sean MacIsaac (macisaac@ximian.com)
  // Paolo Molaro (lupus@ximian.com)
  // Patrik Torstensson (patrik.torstensson@labs2.com)
  //
  // (C) 2001 Ximian, Inc.
  //
  
  //
  // Copyright (C) 2004 Novell, Inc (http://www.novell.com)
  //
  // Permission is hereby granted, free of charge, to any person obtaining
  // a copy of this software and associated documentation files (the
  // "Software"), to deal in the Software without restriction, including
  // without limitation the rights to use, copy, modify, merge, publish,
  // distribute, sublicense, and/or sell copies of the Software, and to
  // permit persons to whom the Software is furnished to do so, subject to
  // the following conditions:
  // 
  // The above copyright notice and this permission notice shall be
  // included in all copies or substantial portions of the Software.
  // 
  // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
  // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
  // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
  // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
  // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
  // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
  // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
  //
  
  #if !FULL_AOT_RUNTIME
  using System.Reflection;
  using System.Reflection.Emit;
  using System.Collections;
  using System.Runtime.CompilerServices;
  using System.Globalization;
  using System.Runtime.Serialization;
  using System.Text;
  using System.Runtime.InteropServices;
  
  namespace System.Reflection
  {
  	/*
  	 * MonoGenericClass represents an instantiation of a generic TypeBuilder. MS
  	 * calls this class TypeBuilderInstantiation (a much better name). MS returns 
  	 * NotImplementedException for many of the methods but we can't do that as gmcs
  	 * depends on them.
  	 */
  	[StructLayout (LayoutKind.Sequential)]
  	sealed class MonoGenericClass :
  		TypeInfo
  	{
  		#region Keep in sync with object-internals.h
  #pragma warning disable 649
  		internal Type generic_type;
  		Type[] type_arguments;
  		bool initialized;
  #pragma warning restore 649
  		#endregion
  
  		Hashtable fields, ctors, methods;
  
  		internal MonoGenericClass ()
  		{
  			// this should not be used
  			throw new InvalidOperationException ();
  		}
  
  		internal MonoGenericClass (Type tb, Type[] args)
  		{
  			this.generic_type = tb;
  			this.type_arguments = args;
  			/*
  			This is a temporary hack until we can fix the rest of the runtime
  			to properly handle this class to be a complete UT.
  
  			We must not regisrer this with the runtime after the type is created
  			otherwise created_type.MakeGenericType will return an instance of MonoGenericClass,
  			which is very very broken.
  			*/
  			if (tb is TypeBuilder && !(tb as TypeBuilder).is_created)
  				register_with_runtime (this);
  			
  		}
  
  		internal override Type InternalResolve ()
  		{
  			Type gtd = generic_type.InternalResolve ();
  			Type[] args = new Type [type_arguments.Length];
  			for (int i = 0; i < type_arguments.Length; ++i)
  				args [i] = type_arguments [i].InternalResolve ();
  			return gtd.MakeGenericType (args);
  		}
  
  		[MethodImplAttribute(MethodImplOptions.InternalCall)]
  		extern void initialize (FieldInfo[] fields);
  
   		[MethodImplAttribute(MethodImplOptions.InternalCall)]
   		internal static extern void register_with_runtime (Type type);
  
  		internal bool IsCreated {
  			get {
  				TypeBuilder tb = generic_type as TypeBuilder;
  				return tb != null ? tb.is_created : true;
  			}
  		}
  
  		private const BindingFlags flags = BindingFlags.Public | BindingFlags.NonPublic |
  		BindingFlags.Static | BindingFlags.Instance | BindingFlags.DeclaredOnly;
  
  		void initialize ()
  		{
  			if (initialized)
  				return;
  
  			MonoGenericClass parent = GetParentType () as MonoGenericClass;
  			if (parent != null)
  				parent.initialize ();
  				
  			initialize (generic_type.GetFields (flags));
  
  			initialized = true;
  		}
  
  		Type GetParentType ()
  		{
  			return InflateType (generic_type.BaseType);		
  		}
  
  		internal Type InflateType (Type type)
  		{
  			return InflateType (type, type_arguments, null);
  		}
  
  		internal Type InflateType (Type type, Type[] method_args)
  		{
  			return InflateType (type, type_arguments, method_args);
  		}
  
  		internal static Type InflateType (Type type, Type[] type_args, Type[] method_args)
  		{
  			if (type == null)
  				return null;
  			if (!type.IsGenericParameter && !type.ContainsGenericParameters)
  				return type;
  			if (type.IsGenericParameter) {
  				if (type.DeclaringMethod == null)
  					return type_args == null ? type : type_args [type.GenericParameterPosition];
  				return method_args == null ? type : method_args [type.GenericParameterPosition];
  			}
  			if (type.IsPointer)
  				return InflateType (type.GetElementType (), type_args, method_args).MakePointerType ();
  			if (type.IsByRef)
  				return InflateType (type.GetElementType (), type_args, method_args).MakeByRefType ();
  			if (type.IsArray) {
  				if (type.GetArrayRank () > 1)
  					return InflateType (type.GetElementType (), type_args, method_args).MakeArrayType (type.GetArrayRank ());
  				
  				if (type.ToString ().EndsWith ("[*]", StringComparison.Ordinal)) /*FIXME, the reflection API doesn't offer a way around this*/
  					return InflateType (type.GetElementType (), type_args, method_args).MakeArrayType (1);
  				return InflateType (type.GetElementType (), type_args, method_args).MakeArrayType ();
  			}
  
  			Type[] args = type.GetGenericArguments ();
  			for (int i = 0; i < args.Length; ++i)
  				args [i] = InflateType (args [i], type_args, method_args);
  
  			Type gtd = type.IsGenericTypeDefinition ? type : type.GetGenericTypeDefinition ();
  			return gtd.MakeGenericType (args);
  		}
  		
  		public override Type BaseType {
  			get { return generic_type.BaseType; }
  		}
  
  		public override Type[] GetInterfaces ()
  		{
  			throw new NotSupportedException ();
  		}
  
  		protected override bool IsValueTypeImpl ()
  		{
  			return generic_type.IsValueType;
  		}
  
  		internal override MethodInfo GetMethod (MethodInfo fromNoninstanciated)
  		{
  			initialize ();
  
  			if (methods == null)
  				methods = new Hashtable ();
  			if (!methods.ContainsKey (fromNoninstanciated))
  				methods [fromNoninstanciated] = new MethodOnTypeBuilderInst (this, fromNoninstanciated);
  			return (MethodInfo)methods [fromNoninstanciated];
  		}
  
  		internal override ConstructorInfo GetConstructor (ConstructorInfo fromNoninstanciated)
  		{
  			initialize ();
  
  			if (ctors == null)
  				ctors = new Hashtable ();
  			if (!ctors.ContainsKey (fromNoninstanciated))
  				ctors [fromNoninstanciated] = new ConstructorOnTypeBuilderInst (this, fromNoninstanciated);
  			return (ConstructorInfo)ctors [fromNoninstanciated];
  		}
  
  		internal override FieldInfo GetField (FieldInfo fromNoninstanciated)
  		{
  			initialize ();
  			if (fields == null)
  				fields = new Hashtable ();
  			if (!fields.ContainsKey (fromNoninstanciated))
  				fields [fromNoninstanciated] = new FieldOnTypeBuilderInst (this, fromNoninstanciated);
  			return (FieldInfo)fields [fromNoninstanciated];
  		}
  		
  		public override MethodInfo[] GetMethods (BindingFlags bf)
  		{
  			throw new NotSupportedException ();
  		}
  
  		public override ConstructorInfo[] GetConstructors (BindingFlags bf)
  		{
  			throw new NotSupportedException ();
  		}
  
  		public override FieldInfo[] GetFields (BindingFlags bf)
  		{
  			throw new NotSupportedException ();
  		}
  
  		public override PropertyInfo[] GetProperties (BindingFlags bf)
  		{
  			throw new NotSupportedException ();
  		}
  
  		public override EventInfo[] GetEvents (BindingFlags bf)
  		{
  			throw new NotSupportedException ();
  		}
  
  		public override Type[] GetNestedTypes (BindingFlags bf)
  		{
  			throw new NotSupportedException ();
  		}
  
  		public override bool IsAssignableFrom (Type c)
  		{
  			throw new NotSupportedException ();
  		}
  
  		public override Type UnderlyingSystemType {
  			get { return this; }
  		}
  
  		public override Assembly Assembly {
  			get { return generic_type.Assembly; }
  		}
  
  		public override Module Module {
  			get { return generic_type.Module; }
  		}
  
  		public override string Name {
  			get { return generic_type.Name; }
  		}
  
  		public override string Namespace {
  			get { return generic_type.Namespace; }
  		}
  
  		public override string FullName {
  			get { return format_name (true, false); }
  		}
  
  		public override string AssemblyQualifiedName {
  			get { return format_name (true, true); }
  		}
  
  		public override Guid GUID {
  			get { throw new NotSupportedException (); }
  		}
  
  		string format_name (bool full_name, bool assembly_qualified)
  		{
  			StringBuilder sb = new StringBuilder (generic_type.FullName);
  
  			sb.Append ("[");
  			for (int i = 0; i < type_arguments.Length; ++i) {
  				if (i > 0)
  					sb.Append (",");
  				
  				string name;
  				if (full_name) {
  					string assemblyName = type_arguments [i].Assembly.FullName;
  					name = type_arguments [i].FullName;
  					if (name != null && assemblyName != null)
  						name = name + ", " + assemblyName;
  				} else {
  					name = type_arguments [i].ToString ();
  				}
  				if (name == null) {
  					return null;
  				}
  				if (full_name)
  					sb.Append ("[");
  				sb.Append (name);
  				if (full_name)
  					sb.Append ("]");
  			}
  			sb.Append ("]");
  			if (assembly_qualified) {
  				sb.Append (", ");
  				sb.Append (generic_type.Assembly.FullName);
  			}
  			return sb.ToString ();
  		}
  
  		public override string ToString ()
  		{
  			return format_name (false, false);
  		}
  
  		public override Type GetGenericTypeDefinition ()
  		{
  			return generic_type;
  		}
  
  		public override Type[] GetGenericArguments ()
  		{
  			Type[] ret = new Type [type_arguments.Length];
  			type_arguments.CopyTo (ret, 0);
  			return ret;
  		}
  
  		public override bool ContainsGenericParameters {
  			get {
  				foreach (Type t in type_arguments) {
  					if (t.ContainsGenericParameters)
  						return true;
  				}
  				return false;
  			}
  		}
  
  		public override bool IsGenericTypeDefinition {
  			get { return false; }
  		}
  
  		public override bool IsGenericType {
  			get { return true; }
  		}
  
  		public override Type DeclaringType {
  			get { return generic_type.DeclaringType; }
  		}
  
  		public override RuntimeTypeHandle TypeHandle {
  			get {
  				throw new NotSupportedException ();
  			}
  		}
  
  		public override Type MakeArrayType ()
  		{
  			return new ArrayType (this, 0);
  		}
  
  		public override Type MakeArrayType (int rank)
  		{
  			if (rank < 1)
  				throw new IndexOutOfRangeException ();
  			return new ArrayType (this, rank);
  		}
  
  		public override Type MakeByRefType ()
  		{
  			return new ByRefType (this);
  		}
  
  		public override Type MakePointerType ()
  		{
  			return new PointerType (this);
  		}
  
  		public override Type GetElementType ()
  		{
  			throw new NotSupportedException ();
  		}
  
  		protected override bool HasElementTypeImpl ()
  		{
  			return false;
  		}
  
  		protected override bool IsCOMObjectImpl ()
  		{
  			return false;
  		}
  
  		protected override bool IsPrimitiveImpl ()
  		{
  			return false;
  		}
  
  		protected override bool IsArrayImpl ()
  		{
  			return false;
  		}
  
  		protected override bool IsByRefImpl ()
  		{
  			return false;
  		}
  
  		protected override bool IsPointerImpl ()
  		{
  			return false;
  		}
  
  		protected override TypeAttributes GetAttributeFlagsImpl ()
  		{
  			return generic_type.Attributes; 
  		}
  
  		//stuff that throws
  		public override Type GetInterface (string name, bool ignoreCase)
  		{
  			throw new NotSupportedException ();
  		}
  
  		public override EventInfo GetEvent (string name, BindingFlags bindingAttr)
  		{
  			throw new NotSupportedException ();
  		}
  
  		public override FieldInfo GetField( string name, BindingFlags bindingAttr)
  		{
  			throw new NotSupportedException ();
  		}
  
  		public override MemberInfo[] GetMembers (BindingFlags bindingAttr)
  		{
  			throw new NotSupportedException ();
  		}
  
  		public override Type GetNestedType (string name, BindingFlags bindingAttr)
  		{
  			throw new NotSupportedException ();
  		}
  
  		public override object InvokeMember (string name, BindingFlags invokeAttr,
  						     Binder binder, object target, object[] args,
  						     ParameterModifier[] modifiers,
  						     CultureInfo culture, string[] namedParameters)
  		{
  			throw new NotSupportedException ();
  		}
  
  		protected override MethodInfo GetMethodImpl (string name, BindingFlags bindingAttr, Binder binder,
  		                                             CallingConventions callConvention, Type[] types,
  		                                             ParameterModifier[] modifiers)
  		{
  			throw new NotSupportedException ();
  		}
  
  		protected override PropertyInfo GetPropertyImpl (string name, BindingFlags bindingAttr, Binder binder,
  		                                                 Type returnType, Type[] types, ParameterModifier[] modifiers)
  		{
  			throw new NotSupportedException ();
  		}
  
  		protected override ConstructorInfo GetConstructorImpl (BindingFlags bindingAttr,
  								       Binder binder,
  								       CallingConventions callConvention,
  								       Type[] types,
  								       ParameterModifier[] modifiers)
  		{
  			throw new NotSupportedException ();
  		}
  
  		//MemberInfo
  		public override bool IsDefined (Type attributeType, bool inherit)
  		{
  			throw new NotSupportedException ();
  		}
  
  		public override object [] GetCustomAttributes (bool inherit)
  		{
  			if (IsCreated)
  				return generic_type.GetCustomAttributes (inherit);
  			throw new NotSupportedException ();
  		}
  
  		public override object [] GetCustomAttributes (Type attributeType, bool inherit)
  		{
  			if (IsCreated)
  				return generic_type.GetCustomAttributes (attributeType, inherit);
  			throw new NotSupportedException ();
  		}
  
  		internal override bool IsUserType {
  			get {
  
gt: 				foreach (var t in type_arguments) {