2014-08-13 10:39:27 +01:00
|
|
|
//
|
|
|
|
// 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)
|
|
|
|
{
|
2015-01-13 10:44:36 +00:00
|
|
|
if (IsCreated)
|
|
|
|
return generic_type.GetCustomAttributes (inherit);
|
2014-08-13 10:39:27 +01:00
|
|
|
throw new NotSupportedException ();
|
|
|
|
}
|
|
|
|
|
|
|
|
public override object [] GetCustomAttributes (Type attributeType, bool inherit)
|
|
|
|
{
|
2015-01-13 10:44:36 +00:00
|
|
|
if (IsCreated)
|
|
|
|
return generic_type.GetCustomAttributes (attributeType, inherit);
|
2014-08-13 10:39:27 +01:00
|
|
|
throw new NotSupportedException ();
|
|
|
|
}
|
|
|
|
|
|
|
|
internal override bool IsUserType {
|
|
|
|
get {
|
|
|
|
foreach (var t in type_arguments) {
|
|
|
|
if (t.IsUserType)
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
#endif
|