Merge pull request #820 from brendanzagaeski/master
[mono.git] / mcs / class / corlib / System.Reflection / CustomAttributeData.cs
1 //
2 // System.Reflection/CustomAttributeData.cs
3 //
4 // Author:
5 //   Zoltan Varga (vargaz@gmail.com)
6 //   Carlos Alberto Cortez (calberto.cortez@gmail.com)
7 //
8 // Copyright (C) 2004 Novell, Inc (http://www.novell.com)
9 //
10 // Permission is hereby granted, free of charge, to any person obtaining
11 // a copy of this software and associated documentation files (the
12 // "Software"), to deal in the Software without restriction, including
13 // without limitation the rights to use, copy, modify, merge, publish,
14 // distribute, sublicense, and/or sell copies of the Software, and to
15 // permit persons to whom the Software is furnished to do so, subject to
16 // the following conditions:
17 // 
18 // The above copyright notice and this permission notice shall be
19 // included in all copies or substantial portions of the Software.
20 // 
21 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
22 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
23 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
24 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
25 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
26 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
27 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
28 //
29
30 using System;
31 using System.Collections.Generic;
32 using System.Runtime.CompilerServices;
33 using System.Runtime.InteropServices;
34 using System.Text;
35
36 namespace System.Reflection {
37
38         [ComVisible (true)]
39         [Serializable]
40 #if NET_4_0
41         public
42 #else
43         public sealed
44 #endif
45         class CustomAttributeData {
46                 class LazyCAttrData {
47                         internal Assembly assembly;
48                         internal IntPtr data;
49                         internal uint data_length;
50                 }
51
52                 ConstructorInfo ctorInfo;
53                 IList<CustomAttributeTypedArgument> ctorArgs;
54                 IList<CustomAttributeNamedArgument> namedArgs;
55                 LazyCAttrData lazyData;
56
57
58 #if NET_4_0
59                 protected CustomAttributeData ()
60                 {
61                 }
62 #endif
63
64                 internal CustomAttributeData (ConstructorInfo ctorInfo, Assembly assembly, IntPtr data, uint data_length)
65                 {
66                         this.ctorInfo = ctorInfo;
67                         this.lazyData = new LazyCAttrData ();
68                         this.lazyData.assembly = assembly;
69                         this.lazyData.data = data;
70                         this.lazyData.data_length = data_length;
71                 }
72
73                 [MethodImplAttribute (MethodImplOptions.InternalCall)]
74                 static extern void ResolveArgumentsInternal (ConstructorInfo ctor, Assembly assembly, IntPtr data, uint data_length, out object[] ctorArgs, out object[] namedArgs); 
75
76                 void ResolveArguments ()
77                 {
78                         object[] ctor_args, named_args;
79                         if (lazyData == null)
80                                 return;
81
82                         ResolveArgumentsInternal (ctorInfo, lazyData.assembly, lazyData.data, lazyData.data_length, out ctor_args, out named_args);
83
84                         this.ctorArgs = Array.AsReadOnly<CustomAttributeTypedArgument>
85                                 (ctor_args != null ? UnboxValues<CustomAttributeTypedArgument> (ctor_args) : EmptyArray<CustomAttributeTypedArgument>.Value);
86                         this.namedArgs = Array.AsReadOnly<CustomAttributeNamedArgument> 
87                                 (named_args != null ? UnboxValues<CustomAttributeNamedArgument> (named_args) : EmptyArray<CustomAttributeNamedArgument>.Value);
88                         
89                         lazyData = null;
90                 }
91                 
92                 [ComVisible (true)]
93                 public
94 #if NET_4_0
95                 virtual
96 #endif
97                 ConstructorInfo Constructor {
98                         get {
99                                 return ctorInfo;
100                         }
101                 }
102
103                 [ComVisible (true)]
104                 public
105 #if NET_4_0
106                 virtual
107 #endif
108                 IList<CustomAttributeTypedArgument> ConstructorArguments {
109                         get {
110                                 ResolveArguments ();
111                                 return ctorArgs;
112                         }
113                 }
114
115                 public
116 #if NET_4_0
117                 virtual
118 #endif
119                 IList<CustomAttributeNamedArgument> NamedArguments {
120                         get {
121                                 ResolveArguments ();
122                                 return namedArgs;
123                         }
124                 }
125
126                 public static IList<CustomAttributeData> GetCustomAttributes (Assembly target) {
127                         return MonoCustomAttrs.GetCustomAttributesData (target);
128                 }
129
130                 public static IList<CustomAttributeData> GetCustomAttributes (MemberInfo target) {
131                         return MonoCustomAttrs.GetCustomAttributesData (target);
132                 }
133
134                 public static IList<CustomAttributeData> GetCustomAttributes (Module target) {
135                         return MonoCustomAttrs.GetCustomAttributesData (target);
136                 }
137
138                 public static IList<CustomAttributeData> GetCustomAttributes (ParameterInfo target) {
139                         return MonoCustomAttrs.GetCustomAttributesData (target);
140                 }
141
142 #if NET_4_5
143                 public Type AttributeType {
144                         get { return ctorInfo.DeclaringType; }
145                 }
146 #endif
147
148                 public override string ToString ()
149                 {
150                         StringBuilder sb = new StringBuilder ();
151
152                         sb.Append ("[" + ctorInfo.DeclaringType.FullName + "(");
153                         for (int i = 0; i < ctorArgs.Count; i++) {
154                                 sb.Append (ctorArgs [i].ToString ());
155                                 if (i + 1 < ctorArgs.Count)
156                                         sb.Append (", ");
157                         }
158
159                         if (namedArgs.Count > 0)
160                                 sb.Append (", ");
161                         
162                         for (int j = 0; j < namedArgs.Count; j++) {
163                                 sb.Append (namedArgs [j].ToString ());
164                                 if (j + 1 < namedArgs.Count)
165                                         sb.Append (", ");
166                         }
167                         sb.AppendFormat (")]");
168
169                         return sb.ToString ();
170                 }
171
172                 static T [] UnboxValues<T> (object [] values)
173                 {
174                         T [] retval = new T [values.Length];
175                         for (int i = 0; i < values.Length; i++)
176                                 retval [i] = (T) values [i];
177
178                         return retval;
179                 }
180
181                 public override bool Equals (object obj)
182                 {
183                         CustomAttributeData other = obj as CustomAttributeData;
184                         if (other == null || other.ctorInfo != ctorInfo ||
185                             other.ctorArgs.Count != ctorArgs.Count ||
186                             other.namedArgs.Count != namedArgs.Count)
187                                 return false;
188                         for (int i = 0; i < ctorArgs.Count; i++)
189                                 if (ctorArgs [i].Equals (other.ctorArgs [i]))
190                                         return false;
191                         for (int i = 0; i < namedArgs.Count; i++) {
192                                 bool matched = false;
193                                 for (int j = 0; j < other.namedArgs.Count; j++)
194                                         if (namedArgs [i].Equals (other.namedArgs [j])) {
195                                                 matched = true;
196                                                 break;
197                                         }
198                                 if (!matched)
199                                         return false;
200                         }
201                         return true;
202                 }
203
204                 public override int GetHashCode ()
205                 {
206                         int ret = ctorInfo == null ? 13 : (ctorInfo.GetHashCode () << 16);
207                         // argument order-dependent
208                         if (ctorArgs != null) {
209                                 for (int i = 0; i < ctorArgs.Count; i++) {
210                                         ret += ret ^ 7 + ctorArgs [i].GetHashCode () << (i * 4);
211                                 }
212                         }
213                         // argument order-independent
214                         if (namedArgs != null) {
215                                 for (int i = 0; i < namedArgs.Count; i++)
216                                         ret += (namedArgs [i].GetHashCode () << 5);
217                         }
218                         return ret;
219                 }
220         }
221
222 }
223