//
// System.Type.cs
//
-// Author:
+// Authors:
// Miguel de Icaza (miguel@ximian.com)
+// Marek Safar (marek.safar@gmail.com)
//
// (C) Ximian, Inc. http://www.ximian.com
//
using System.Reflection;
using System.Reflection.Emit;
using System.Collections;
+using System.Collections.Generic;
using System.Runtime.InteropServices;
using System.Runtime.CompilerServices;
using System.Globalization;
[Serializable]
[ClassInterface (ClassInterfaceType.None)]
-#if NET_2_0
[ComVisible (true)]
[ComDefaultInterface (typeof (_Type))]
-#endif
+ [StructLayout (LayoutKind.Sequential)]
public abstract class Type : MemberInfo, IReflect, _Type {
internal RuntimeTypeHandle _impl;
public static readonly MemberFilter FilterAttribute = new MemberFilter (FilterAttribute_impl);
public static readonly MemberFilter FilterName = new MemberFilter (FilterName_impl);
public static readonly MemberFilter FilterNameIgnoreCase = new MemberFilter (FilterNameIgnoreCase_impl);
- public static readonly object Missing;
+ public static readonly object Missing = System.Reflection.Missing.Value;
internal const BindingFlags DefaultBindingFlags =
BindingFlags.Public | BindingFlags.Static | BindingFlags.Instance;
return false; // because m.Name cannot be null or empty
if (name [name.Length-1] == '*')
- return string.Compare (name, 0, m.Name, 0, name.Length-1, false, CultureInfo.InvariantCulture) == 0;
+ return string.CompareOrdinal (name, 0, m.Name, 0, name.Length-1) == 0;
return name.Equals (m.Name);
}
return false; // because m.Name cannot be null or empty
if (name [name.Length-1] == '*')
- return string.Compare (name, 0, m.Name, 0, name.Length-1, true, CultureInfo.InvariantCulture) == 0;
+ return string.Compare (name, 0, m.Name, 0, name.Length-1, StringComparison.OrdinalIgnoreCase) == 0;
- return String.Compare (name, m.Name, true, CultureInfo.InvariantCulture) == 0;
+ return string.Equals (name, m.Name, StringComparison.OrdinalIgnoreCase);
}
static bool FilterAttribute_impl (MemberInfo m, object filterCriteria)
return IsCOMObjectImpl ();
}
}
+
+#if NET_4_5
+ public virtual bool IsConstructedGenericType {
+ get {
+ throw new NotImplementedException ();
+ }
+ }
+#endif
public bool IsContextful {
get {
}
}
- public bool IsEnum {
+ public
+#if NET_4_0
+ virtual
+#endif
+ bool IsEnum {
get {
return IsSubclassOf (typeof (Enum));
}
}
}
- public bool IsSerializable {
+ public
+#if NET_4_0
+ virtual
+#endif
+ bool IsSerializable {
get {
if ((Attributes & TypeAttributes.Serializable) != 0)
return true;
}
public override MemberTypes MemberType {
- get {return MemberTypes.TypeInfo;}
+ get {
+ return MemberTypes.TypeInfo;
+ }
}
-#if NET_2_0 || BOOTSTRAP_NET_2_0
- override
-#endif
- public abstract Module Module {get;}
+ public abstract override Module Module {
+ get;
+ }
public abstract string Namespace {get;}
}
}
-#if NET_2_0
public virtual RuntimeTypeHandle TypeHandle {
- get { return default (RuntimeTypeHandle); }
+ get { throw new ArgumentException ("Derived class must provide implementation."); }
}
-#else
- public abstract RuntimeTypeHandle TypeHandle {get;}
-#endif
-#if NET_2_0
[ComVisible (true)]
-#endif
public ConstructorInfo TypeInitializer {
get {
return GetConstructorImpl (
public override bool Equals (object o)
{
- if (o == null)
- return false;
-
- Type cmp = o as Type;
- if (cmp == null)
+#if NET_4_0
+ return Equals (o as Type);
+#else
+ if (o == this)
+ return true;
+
+ Type me = UnderlyingSystemType;
+ if (me == null)
return false;
- return Equals (cmp);
+ return me.EqualsInternal (o as Type);
+#endif
}
- public bool Equals (Type o) {
+#if NET_4_0
+ public virtual bool Equals (Type o)
+ {
+ if ((object)o == (object)this)
+ return true;
+ if ((object)o == null)
+ return false;
+ Type me = UnderlyingSystemType;
+ if ((object)me == null)
+ return false;
+
+ o = o.UnderlyingSystemType;
+ if ((object)o == null)
+ return false;
+ if ((object)o == (object)this)
+ return true;
+ return me.EqualsInternal (o);
+ }
+#else
+ public bool Equals (Type o)
+ {
+
+ if (o == this)
+ return true;
if (o == null)
return false;
- return UnderlyingSystemType.EqualsInternal (o.UnderlyingSystemType);
+ Type me = UnderlyingSystemType;
+ if (me == null)
+ return false;
+ return me.EqualsInternal (o.UnderlyingSystemType);
+ }
+#endif
+#if NET_4_0
+ [MonoTODO ("Implement it properly once 4.0 impl details are known.")]
+ public static bool operator == (Type left, Type right)
+ {
+ return Object.ReferenceEquals (left, right);
+ }
+
+ [MonoTODO ("Implement it properly once 4.0 impl details are known.")]
+ public static bool operator != (Type left, Type right)
+ {
+ return !Object.ReferenceEquals (left, right);
+ }
+
+ [MonoInternalNote ("Reimplement this in MonoType for bonus speed")]
+ public virtual Type GetEnumUnderlyingType () {
+ if (!IsEnum)
+ throw new ArgumentException ("Type is not an enumeration", "enumType");
+
+ var fields = GetFields (BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance);
+
+ if (fields == null || fields.Length != 1)
+ throw new ArgumentException ("An enum must have exactly one instance field", "enumType");
+
+ return fields [0].FieldType;
+ }
+
+ [MonoInternalNote ("Reimplement this in MonoType for bonus speed")]
+ public virtual string[] GetEnumNames () {
+ if (!IsEnum)
+ throw new ArgumentException ("Type is not an enumeration", "enumType");
+
+ var fields = GetFields (BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Static);
+
+ string [] names = new string [fields.Length];
+ if (0 != names.Length) {
+ for (int i = 0; i < fields.Length; ++i)
+ names [i] = fields [i].Name;
+
+ var et = GetEnumUnderlyingType ();
+ var values = Array.CreateInstance (et, names.Length);
+ for (int i = 0; i < fields.Length; ++i)
+ values.SetValue (fields [i].GetValue (null), i);
+ MonoEnumInfo.SortEnums (et, values, names);
+ }
+
+ return names;
+ }
+
+ static NotImplementedException CreateNIE () {
+ return new NotImplementedException ();
+ }
+
+ public virtual Array GetEnumValues () {
+ if (!IsEnum)
+ throw new ArgumentException ("Type is not an enumeration", "enumType");
+
+ throw CreateNIE ();
+ }
+
+ bool IsValidEnumType (Type type) {
+ return (type.IsPrimitive && type != typeof (bool) && type != typeof (double) && type != typeof (float)) || type.IsEnum;
+ }
+
+ [MonoInternalNote ("Reimplement this in MonoType for bonus speed")]
+ public virtual string GetEnumName (object value) {
+ if (value == null)
+ throw new ArgumentException ("Value is null", "value");
+ if (!IsValidEnumType (value.GetType ()))
+ throw new ArgumentException ("Value is not the enum or a valid enum underlying type", "value");
+ if (!IsEnum)
+ throw new ArgumentException ("Type is not an enumeration", "enumType");
+
+ object obj = null;
+ var fields = GetFields (BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Static);
+
+ for (int i = 0; i < fields.Length; ++i) {
+ var fv = fields [i].GetValue (null);
+ if (obj == null) {
+ try {
+ //XXX we can't use 'this' as argument as it might be an UserType
+ obj = Enum.ToObject (fv.GetType (), value);
+ } catch (OverflowException) {
+ return null;
+ } catch (InvalidCastException) {
+ throw new ArgumentException ("Value is not valid", "value");
+ }
+ }
+ if (fv.Equals (obj))
+ return fields [i].Name;
+ }
+
+ return null;
+ }
+
+ [MonoInternalNote ("Reimplement this in MonoType for bonus speed")]
+ public virtual bool IsEnumDefined (object value) {
+ if (value == null)
+ throw new ArgumentException ("Value is null", "value");
+ if (!IsEnum)
+ throw new ArgumentException ("Type is not an enumeration", "enumType");
+
+ Type vt = value.GetType ();
+ if (!IsValidEnumType (vt) && vt != typeof (string))
+ throw new InvalidOperationException ("Value is not the enum or a valid enum underlying type");
+
+ var fields = GetFields (BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Static);
+
+ if (value is string) {
+ for (int i = 0; i < fields.Length; ++i) {
+ if (fields [i].Name.Equals (value))
+ return true;
+ }
+ } else {
+ if (vt != this && vt != GetEnumUnderlyingType ())
+ throw new ArgumentException ("Value is not the enum or a valid enum underlying type", "value");
+
+ object obj = null;
+ for (int i = 0; i < fields.Length; ++i) {
+ var fv = fields [i].GetValue (null);
+ if (obj == null) {
+ try {
+ //XXX we can't use 'this' as argument as it might be an UserType
+ obj = Enum.ToObject (fv.GetType (), value);
+ } catch (OverflowException) {
+ return false;
+ } catch (InvalidCastException) {
+ throw new ArgumentException ("Value is not valid", "value");
+ }
+ }
+ if (fv.Equals (obj))
+ return true;
+ }
+ }
+ return false;
+ }
+
+ public static Type GetType (string typeName, Func<AssemblyName,Assembly> assemblyResolver, Func<Assembly,string,bool,Type> typeResolver)
+ {
+ return GetType (typeName, assemblyResolver, typeResolver, false, false);
+ }
+
+ public static Type GetType (string typeName, Func<AssemblyName,Assembly> assemblyResolver, Func<Assembly,string,bool,Type> typeResolver, bool throwOnError)
+ {
+ return GetType (typeName, assemblyResolver, typeResolver, throwOnError, false);
+ }
+
+ public static Type GetType (string typeName, Func<AssemblyName,Assembly> assemblyResolver, Func<Assembly,string,bool,Type> typeResolver, bool throwOnError, bool ignoreCase)
+ {
+ TypeSpec spec = TypeSpec.Parse (typeName);
+ return spec.Resolve (assemblyResolver, typeResolver, throwOnError, ignoreCase);
+ }
+
+ public virtual bool IsSecurityTransparent
+ {
+ get { throw CreateNIE (); }
+ }
+
+ public virtual bool IsSecurityCritical
+ {
+ get { throw CreateNIE (); }
}
+ public virtual bool IsSecuritySafeCritical
+ {
+ get { throw CreateNIE (); }
+ }
+#endif
+
[MethodImplAttribute(MethodImplOptions.InternalCall)]
internal extern bool EqualsInternal (Type type);
public static Type GetType(string typeName)
{
if (typeName == null)
-#if NET_2_0
throw new ArgumentNullException ("TypeName");
-#else
- throw new ArgumentNullException ("className");
-#endif
return internal_from_name (typeName, false, false);
}
public static Type GetType(string typeName, bool throwOnError)
{
if (typeName == null)
-#if NET_2_0
throw new ArgumentNullException ("TypeName");
-#else
- throw new ArgumentNullException ("className");
-#endif
Type type = internal_from_name (typeName, throwOnError, false);
if (throwOnError && type == null)
public static Type GetType(string typeName, bool throwOnError, bool ignoreCase)
{
if (typeName == null)
-#if NET_2_0
throw new ArgumentNullException ("TypeName");
-#else
- throw new ArgumentNullException ("className");
-#endif
Type t = internal_from_name (typeName, throwOnError, ignoreCase);
if (throwOnError && t == null)
[MethodImplAttribute(MethodImplOptions.InternalCall)]
internal extern static TypeCode GetTypeCodeInternal (Type type);
- public static TypeCode GetTypeCode (Type type) {
+#if NET_4_0
+ protected virtual
+#endif
+ TypeCode GetTypeCodeImpl () {
+ Type type = this;
if (type is MonoType)
return GetTypeCodeInternal (type);
- if (type == null)
- /* MS.NET returns this */
- return TypeCode.Empty;
+ if (type is TypeBuilder)
+ return ((TypeBuilder)type).GetTypeCodeInternal ();
type = type.UnderlyingSystemType;
return GetTypeCodeInternal (type);
}
+ public static TypeCode GetTypeCode (Type type) {
+ if (type == null)
+ /* MS.NET returns this */
+ return TypeCode.Empty;
+ return type.GetTypeCodeImpl ();
+ }
+
[MonoTODO("This operation is currently not supported by Mono")]
public static Type GetTypeFromCLSID (Guid clsid)
{
public static Type GetTypeFromHandle (RuntimeTypeHandle handle)
{
if (handle.Value == IntPtr.Zero)
-#if NET_2_0
// This is not consistent with the other GetXXXFromHandle methods, but
// MS.NET seems to do this
return null;
-#else
- throw new ArgumentException ("The handle is invalid.");
-#endif
return internal_from_handle (handle.Value);
}
public static RuntimeTypeHandle GetTypeHandle (object o)
{
if (o == null)
-#if NET_2_0
throw new ArgumentNullException ();
-#else
- throw new ArgumentNullException ("o");
-#endif
return o.GetType().TypeHandle;
}
return base.GetType ();
}
-#if NET_2_0
[ComVisible (true)]
-#endif
public virtual bool IsSubclassOf (Type c)
{
if (c == null || c == this)
if (filter == null)
throw new ArgumentNullException ("filter");
- ArrayList ifaces = new ArrayList ();
+ var ifaces = new List<Type> ();
foreach (Type iface in GetInterfaces ()) {
if (filter (iface, filterCriteria))
ifaces.Add (iface);
}
- return (Type []) ifaces.ToArray (typeof (Type));
+ return ifaces.ToArray ();
}
public Type GetInterface (string name) {
[MethodImplAttribute(MethodImplOptions.InternalCall)]
internal static extern void GetInterfaceMapData (Type t, Type iface, out MethodInfo[] targets, out MethodInfo[] methods);
-#if NET_2_0
[ComVisible (true)]
-#endif
public virtual InterfaceMapping GetInterfaceMap (Type interfaceType) {
- InterfaceMapping res;
+ if (!IsSystemType)
+ throw new NotSupportedException ("Derived classes must provide an implementation.");
if (interfaceType == null)
throw new ArgumentNullException ("interfaceType");
+ if (!interfaceType.IsSystemType)
+ throw new ArgumentException ("interfaceType", "Type is an user type");
+ InterfaceMapping res;
if (!interfaceType.IsInterface)
throw new ArgumentException (Locale.GetText ("Argument must be an interface."), "interfaceType");
if (IsInterface)
Type systemType = UnderlyingSystemType;
if (!systemType.IsSystemType)
return false;
- return systemType.IsAssignableFrom (c);
+
+ Type other = c.UnderlyingSystemType;
+ if (!other.IsSystemType)
+ return false;
+
+ return systemType.IsAssignableFrom (other);
}
if (!c.IsSystemType) {
}
[MethodImplAttribute(MethodImplOptions.InternalCall)]
- public extern virtual bool IsInstanceOfType (object o);
+ extern static bool IsInstanceOfType (Type type, object o);
+
+ public virtual bool IsInstanceOfType (object o)
+ {
+ Type type = UnderlyingSystemType;
+ if (!type.IsSystemType)
+ return false;
+ return IsInstanceOfType (type, o);
+ }
public virtual int GetArrayRank ()
{
return typeof (MarshalByRefObject).IsAssignableFrom (this);
}
-#if NET_2_0
[ComVisible (true)]
-#endif
public ConstructorInfo GetConstructor (Type[] types)
{
return GetConstructor (BindingFlags.Public|BindingFlags.Instance, null, CallingConventions.Any, types, null);
}
-#if NET_2_0
[ComVisible (true)]
-#endif
public ConstructorInfo GetConstructor (BindingFlags bindingAttr, Binder binder,
Type[] types, ParameterModifier[] modifiers)
{
return GetConstructor (bindingAttr, binder, CallingConventions.Any, types, modifiers);
}
-#if NET_2_0
[ComVisible (true)]
-#endif
public ConstructorInfo GetConstructor (BindingFlags bindingAttr, Binder binder,
CallingConventions callConvention,
Type[] types, ParameterModifier[] modifiers)
return GetConstructorImpl (bindingAttr, binder, callConvention, types, modifiers);
}
-#if NET_2_0
[ComVisible (true)]
-#endif
public ConstructorInfo[] GetConstructors ()
{
return GetConstructors (BindingFlags.Public | BindingFlags.Instance);
}
-#if NET_2_0
[ComVisible (true)]
-#endif
public abstract ConstructorInfo[] GetConstructors (BindingFlags bindingAttr);
public virtual MemberInfo[] GetDefaultMembers ()
}
}
if ((memberType & MemberTypes.Property) != 0) {
- PropertyInfo[] c;
- int count = l.Count;
- Type ptype;
+ PropertyInfo[] c = GetProperties (bindingAttr);
+
+
if (filter != null) {
- ptype = this;
- while ((l.Count == count) && (ptype != null)) {
- c = ptype.GetProperties (bindingAttr);
- foreach (MemberInfo m in c) {
- if (filter (m, filterCriteria))
- l.Add (m);
- }
- ptype = ptype.BaseType;
+ foreach (MemberInfo m in c) {
+ if (filter (m, filterCriteria))
+ l.Add (m);
}
} else {
- c = GetProperties (bindingAttr);
l.AddRange (c);
}
+
}
if ((memberType & MemberTypes.Event) != 0) {
EventInfo[] c = GetEvents (bindingAttr);
return FullName;
}
+ internal virtual Type InternalResolve ()
+ {
+ return UnderlyingSystemType;
+ }
+
internal bool IsSystemType {
get {
return _impl.Value != IntPtr.Zero;
}
}
+
+#if NET_4_5
+ public virtual Type[] GenericTypeArguments {
+ get {
+ return IsGenericType ? GetGenericArguments () : EmptyTypes;
+ }
+ }
+#endif
-#if NET_2_0 || BOOTSTRAP_NET_2_0
public virtual Type[] GetGenericArguments ()
{
throw new NotSupportedException ();
[MethodImplAttribute(MethodImplOptions.InternalCall)]
get;
}
-
+
[MethodImplAttribute(MethodImplOptions.InternalCall)]
static extern Type MakeGenericType (Type gt, Type [] types);
public virtual Type MakeGenericType (params Type[] typeArguments)
{
+ if (IsUserType)
+ throw new NotSupportedException ();
if (!IsGenericTypeDefinition)
throw new InvalidOperationException ("not a generic type definition");
if (typeArguments == null)
if (GetGenericArguments().Length != typeArguments.Length)
throw new ArgumentException (String.Format ("The type or method has {0} generic parameter(s) but {1} generic argument(s) where provided. A generic argument must be provided for each generic parameter.", GetGenericArguments ().Length, typeArguments.Length), "typeArguments");
+ bool hasUserType = false;
+
Type[] systemTypes = new Type[typeArguments.Length];
for (int i = 0; i < typeArguments.Length; ++i) {
Type t = typeArguments [i];
if (t == null)
throw new ArgumentNullException ("typeArguments");
- if (!(t is EnumBuilder || t is TypeBuilder))
- t = t.UnderlyingSystemType;
- if (t == null || !t.IsSystemType)
- throw new ArgumentNullException ("typeArguments");
+
+ if (!(t is MonoType))
+ hasUserType = true;
systemTypes [i] = t;
}
+ if (hasUserType) {
+ return new MonoGenericClass (this, typeArguments);
+ }
+
Type res = MakeGenericType (this, systemTypes);
if (res == null)
throw new TypeLoadException ();
public virtual GenericParameterAttributes GenericParameterAttributes {
get {
+ if (!IsSystemType)
+ throw new NotSupportedException ("Derived classes must provide an implementation.");
+
if (!IsGenericParameter)
throw new InvalidOperationException ();
public virtual Type[] GetGenericParameterConstraints ()
{
+ if (!IsSystemType)
+ throw new InvalidOperationException ();
+
if (!IsGenericParameter)
throw new InvalidOperationException ();
public virtual Type MakeArrayType ()
{
+ if (!IsSystemType)
+ throw new NotSupportedException ("Derived classes must provide an implementation.");
return make_array_type (0);
}
public virtual Type MakeArrayType (int rank)
{
- if (rank < 1)
+ if (!IsSystemType)
+ throw new NotSupportedException ("Derived classes must provide an implementation.");
+ if (rank < 1 || rank > 255)
throw new IndexOutOfRangeException ();
-
return make_array_type (rank);
}
public virtual Type MakeByRefType ()
{
+ if (!IsSystemType)
+ throw new NotSupportedException ("Derived classes must provide an implementation.");
+ if (IsByRef)
+ throw new TypeLoadException ("Can not call MakeByRefType on a ByRef type");
return make_byref_type ();
}
[MethodImplAttribute(MethodImplOptions.InternalCall)]
- public extern virtual Type MakePointerType ();
+ static extern Type MakePointerType (Type type);
+
+ public virtual Type MakePointerType ()
+ {
+ if (!IsSystemType)
+ throw new NotSupportedException ("Derived classes must provide an implementation.");
+ return MakePointerType (this);
+ }
public static Type ReflectionOnlyGetType (string typeName,
bool throwIfNotFound,
public virtual StructLayoutAttribute StructLayoutAttribute {
get {
- LayoutKind kind;
-
- if (IsLayoutSequential)
- kind = LayoutKind.Sequential;
- else if (IsExplicitLayout)
- kind = LayoutKind.Explicit;
- else
- kind = LayoutKind.Auto;
-
- StructLayoutAttribute attr = new StructLayoutAttribute (kind);
+#if NET_4_0
+ throw new NotSupportedException ();
+#else
+ return GetStructLayoutAttribute ();
+#endif
+ }
+ }
+
+ internal StructLayoutAttribute GetStructLayoutAttribute ()
+ {
+ LayoutKind kind;
- if (IsUnicodeClass)
- attr.CharSet = CharSet.Unicode;
- else if (IsAnsiClass)
- attr.CharSet = CharSet.Ansi;
- else
- attr.CharSet = CharSet.Auto;
+ if (IsLayoutSequential)
+ kind = LayoutKind.Sequential;
+ else if (IsExplicitLayout)
+ kind = LayoutKind.Explicit;
+ else
+ kind = LayoutKind.Auto;
- if (kind != LayoutKind.Auto)
- GetPacking (out attr.Pack, out attr.Size);
+ StructLayoutAttribute attr = new StructLayoutAttribute (kind);
- return attr;
+ if (IsUnicodeClass)
+ attr.CharSet = CharSet.Unicode;
+ else if (IsAnsiClass)
+ attr.CharSet = CharSet.Ansi;
+ else
+ attr.CharSet = CharSet.Auto;
+
+ if (kind != LayoutKind.Auto) {
+ int packing;
+ GetPacking (out packing, out attr.Size);
+ // 0 means no data provided, we end up with default value
+ if (packing != 0)
+ attr.Pack = packing;
}
+
+ return attr;
}
internal object[] GetPseudoCustomAttributes ()
return attrs;
}
-#endif
#if NET_4_0
public virtual bool IsEquivalentTo (Type other)
/*
* Return whenever this object is an instance of a user defined subclass
* of System.Type or an instance of TypeDelegator.
+ * A user defined type is not simply the opposite of a system type.
+ * It's any class that's neither a SRE or runtime baked type.
*/
- internal bool IsUserType {
+ internal virtual bool IsUserType {
get {
- /*
- * subclasses cannot modify _impl so if it is zero, it means the
- * type is not created by the runtime.
- */
- return _impl.Value == IntPtr.Zero &&
- (GetType ().Assembly != typeof (Type).Assembly || GetType () == typeof (TypeDelegator));
+ return true;
}
}