[corlib] Defer TypeInfo instantiation logic in DefinedTypes. Fixes #19082
[mono.git] / mcs / class / corlib / System.Reflection / CustomAttributeData.cs
index 2ebf4cfef7b7ab22226e8380775ed8abe9525cc3..615bf7de8acf76df4ad102c95cd8f9ba1140755e 100644 (file)
@@ -27,8 +27,6 @@
 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 //
 
-#if NET_2_0
-
 using System;
 using System.Collections.Generic;
 using System.Runtime.CompilerServices;
@@ -39,37 +37,88 @@ namespace System.Reflection {
 
        [ComVisible (true)]
        [Serializable]
-       public sealed class CustomAttributeData {
+#if NET_4_0
+       public
+#else
+       public sealed
+#endif
+       class CustomAttributeData {
+               class LazyCAttrData {
+                       internal Assembly assembly;
+                       internal IntPtr data;
+                       internal uint data_length;
+               }
+
                ConstructorInfo ctorInfo;
                IList<CustomAttributeTypedArgument> ctorArgs;
                IList<CustomAttributeNamedArgument> namedArgs;
+               LazyCAttrData lazyData;
+
 
-               internal CustomAttributeData (ConstructorInfo ctorInfo, object [] ctorArgs, object [] namedArgs)
+#if NET_4_0
+               protected CustomAttributeData ()
+               {
+               }
+#endif
+
+               internal CustomAttributeData (ConstructorInfo ctorInfo, Assembly assembly, IntPtr data, uint data_length)
                {
                        this.ctorInfo = ctorInfo;
-                       
-                       this.ctorArgs = Array.AsReadOnly<CustomAttributeTypedArgument> 
-                               (ctorArgs != null ? UnboxValues<CustomAttributeTypedArgument> (ctorArgs) : new CustomAttributeTypedArgument [0]);
-                       
-                       this.namedArgs = Array.AsReadOnly<CustomAttributeNamedArgument> 
-                               (namedArgs != null ? UnboxValues<CustomAttributeNamedArgument> (namedArgs) : new CustomAttributeNamedArgument [0]);
+                       this.lazyData = new LazyCAttrData ();
+                       this.lazyData.assembly = assembly;
+                       this.lazyData.data = data;
+                       this.lazyData.data_length = data_length;
                }
 
+               [MethodImplAttribute (MethodImplOptions.InternalCall)]
+               static extern void ResolveArgumentsInternal (ConstructorInfo ctor, Assembly assembly, IntPtr data, uint data_length, out object[] ctorArgs, out object[] namedArgs); 
+
+               void ResolveArguments ()
+               {
+                       object[] ctor_args, named_args;
+                       if (lazyData == null)
+                               return;
+
+                       ResolveArgumentsInternal (ctorInfo, lazyData.assembly, lazyData.data, lazyData.data_length, out ctor_args, out named_args);
+
+                       this.ctorArgs = Array.AsReadOnly<CustomAttributeTypedArgument>
+                               (ctor_args != null ? UnboxValues<CustomAttributeTypedArgument> (ctor_args) : EmptyArray<CustomAttributeTypedArgument>.Value);
+                       this.namedArgs = Array.AsReadOnly<CustomAttributeNamedArgument> 
+                               (named_args != null ? UnboxValues<CustomAttributeNamedArgument> (named_args) : EmptyArray<CustomAttributeNamedArgument>.Value);
+                       
+                       lazyData = null;
+               }
+               
                [ComVisible (true)]
-               public ConstructorInfo Constructor {
+               public
+#if NET_4_0
+               virtual
+#endif
+               ConstructorInfo Constructor {
                        get {
                                return ctorInfo;
                        }
                }
 
-               public IList<CustomAttributeTypedArgument> ConstructorArguments {
+               [ComVisible (true)]
+               public
+#if NET_4_0
+               virtual
+#endif
+               IList<CustomAttributeTypedArgument> ConstructorArguments {
                        get {
+                               ResolveArguments ();
                                return ctorArgs;
                        }
                }
 
-               public IList<CustomAttributeNamedArgument> NamedArguments {
+               public
+#if NET_4_0
+               virtual
+#endif
+               IList<CustomAttributeNamedArgument> NamedArguments {
                        get {
+                               ResolveArguments ();
                                return namedArgs;
                        }
                }
@@ -90,11 +139,17 @@ namespace System.Reflection {
                        return MonoCustomAttrs.GetCustomAttributesData (target);
                }
 
+#if NET_4_5
+               public Type AttributeType {
+                       get { return ctorInfo.DeclaringType; }
+               }
+#endif
+
                public override string ToString ()
                {
                        StringBuilder sb = new StringBuilder ();
 
-                       sb.Append ("[" + ctorInfo.DeclaringType.Name + " (");
+                       sb.Append ("[" + ctorInfo.DeclaringType.FullName + "(");
                        for (int i = 0; i < ctorArgs.Count; i++) {
                                sb.Append (ctorArgs [i].ToString ());
                                if (i + 1 < ctorArgs.Count)
@@ -122,9 +177,47 @@ namespace System.Reflection {
 
                        return retval;
                }
+
+               public override bool Equals (object obj)
+               {
+                       CustomAttributeData other = obj as CustomAttributeData;
+                       if (other == null || other.ctorInfo != ctorInfo ||
+                           other.ctorArgs.Count != ctorArgs.Count ||
+                           other.namedArgs.Count != namedArgs.Count)
+                               return false;
+                       for (int i = 0; i < ctorArgs.Count; i++)
+                               if (ctorArgs [i].Equals (other.ctorArgs [i]))
+                                       return false;
+                       for (int i = 0; i < namedArgs.Count; i++) {
+                               bool matched = false;
+                               for (int j = 0; j < other.namedArgs.Count; j++)
+                                       if (namedArgs [i].Equals (other.namedArgs [j])) {
+                                               matched = true;
+                                               break;
+                                       }
+                               if (!matched)
+                                       return false;
+                       }
+                       return true;
+               }
+
+               public override int GetHashCode ()
+               {
+                       int ret = ctorInfo == null ? 13 : (ctorInfo.GetHashCode () << 16);
+                       // argument order-dependent
+                       if (ctorArgs != null) {
+                               for (int i = 0; i < ctorArgs.Count; i++) {
+                                       ret += ret ^ 7 + ctorArgs [i].GetHashCode () << (i * 4);
+                               }
+                       }
+                       // argument order-independent
+                       if (namedArgs != null) {
+                               for (int i = 0; i < namedArgs.Count; i++)
+                                       ret += (namedArgs [i].GetHashCode () << 5);
+                       }
+                       return ret;
+               }
        }
 
 }
 
-#endif
-