~ubuntu-branches/ubuntu/trusty/monodevelop/trusty-proposed

« back to all changes in this revision

Viewing changes to external/ikvm/reflect/CustomAttributeData.cs

  • Committer: Package Import Robot
  • Author(s): Jo Shields
  • Date: 2013-05-12 09:46:03 UTC
  • mto: This revision was merged to the branch mainline in revision 29.
  • Revision ID: package-import@ubuntu.com-20130512094603-mad323bzcxvmcam0
Tags: upstream-4.0.5+dfsg
ImportĀ upstreamĀ versionĀ 4.0.5+dfsg

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
  Copyright (C) 2009-2012 Jeroen Frijters
 
3
 
 
4
  This software is provided 'as-is', without any express or implied
 
5
  warranty.  In no event will the authors be held liable for any damages
 
6
  arising from the use of this software.
 
7
 
 
8
  Permission is granted to anyone to use this software for any purpose,
 
9
  including commercial applications, and to alter it and redistribute it
 
10
  freely, subject to the following restrictions:
 
11
 
 
12
  1. The origin of this software must not be misrepresented; you must not
 
13
     claim that you wrote the original software. If you use this software
 
14
     in a product, an acknowledgment in the product documentation would be
 
15
     appreciated but is not required.
 
16
  2. Altered source versions must be plainly marked as such, and must not be
 
17
     misrepresented as being the original software.
 
18
  3. This notice may not be removed or altered from any source distribution.
 
19
 
 
20
  Jeroen Frijters
 
21
  jeroen@frijters.net
 
22
  
 
23
*/
 
24
using System;
 
25
using System.Collections.Generic;
 
26
using System.Text;
 
27
using System.IO;
 
28
using IKVM.Reflection.Reader;
 
29
using IKVM.Reflection.Emit;
 
30
using IKVM.Reflection.Metadata;
 
31
 
 
32
namespace IKVM.Reflection
 
33
{
 
34
        public sealed class CustomAttributeData
 
35
        {
 
36
                internal static readonly IList<CustomAttributeData> EmptyList = new List<CustomAttributeData>(0).AsReadOnly();
 
37
 
 
38
                /*
 
39
                 * There are several states a CustomAttributeData object can be in:
 
40
                 * 
 
41
                 * 1) Unresolved Custom Attribute
 
42
                 *    - customAttributeIndex >= 0
 
43
                 *    - declSecurityIndex == -1
 
44
                 *    - declSecurityBlob == null
 
45
                 *    - lazyConstructor = null
 
46
                 *    - lazyConstructorArguments = null
 
47
                 *    - lazyNamedArguments = null
 
48
                 * 
 
49
                 * 2) Resolved Custom Attribute
 
50
                 *    - customAttributeIndex >= 0
 
51
                 *    - declSecurityIndex == -1
 
52
                 *    - declSecurityBlob == null
 
53
                 *    - lazyConstructor != null
 
54
                 *    - lazyConstructorArguments != null
 
55
                 *    - lazyNamedArguments != null
 
56
                 *    
 
57
                 * 3) Pre-resolved Custom Attribute
 
58
                 *    - customAttributeIndex = -1
 
59
                 *    - declSecurityIndex == -1
 
60
                 *    - declSecurityBlob == null
 
61
                 *    - lazyConstructor != null
 
62
                 *    - lazyConstructorArguments != null
 
63
                 *    - lazyNamedArguments != null
 
64
                 *    
 
65
                 * 4) Pseudo Custom Attribute, .NET 1.x declarative security or result of CustomAttributeBuilder.ToData()
 
66
                 *    - customAttributeIndex = -1
 
67
                 *    - declSecurityIndex == -1
 
68
                 *    - declSecurityBlob == null
 
69
                 *    - lazyConstructor != null
 
70
                 *    - lazyConstructorArguments != null
 
71
                 *    - lazyNamedArguments != null
 
72
                 *    
 
73
                 * 5) Unresolved declarative security
 
74
                 *    - customAttributeIndex = -1
 
75
                 *    - declSecurityIndex >= 0
 
76
                 *    - declSecurityBlob != null
 
77
                 *    - lazyConstructor != null
 
78
                 *    - lazyConstructorArguments != null
 
79
                 *    - lazyNamedArguments == null
 
80
                 * 
 
81
                 * 6) Resolved declarative security
 
82
                 *    - customAttributeIndex = -1
 
83
                 *    - declSecurityIndex >= 0
 
84
                 *    - declSecurityBlob == null
 
85
                 *    - lazyConstructor != null
 
86
                 *    - lazyConstructorArguments != null
 
87
                 *    - lazyNamedArguments != null
 
88
                 * 
 
89
                 */
 
90
                private readonly Module module;
 
91
                private readonly int customAttributeIndex;
 
92
                private readonly int declSecurityIndex;
 
93
                private readonly byte[] declSecurityBlob;
 
94
                private ConstructorInfo lazyConstructor;
 
95
                private IList<CustomAttributeTypedArgument> lazyConstructorArguments;
 
96
                private IList<CustomAttributeNamedArgument> lazyNamedArguments;
 
97
 
 
98
                // 1) Unresolved Custom Attribute
 
99
                internal CustomAttributeData(Module module, int index)
 
100
                {
 
101
                        this.module = module;
 
102
                        this.customAttributeIndex = index;
 
103
                        this.declSecurityIndex = -1;
 
104
                }
 
105
 
 
106
                // 4) Pseudo Custom Attribute, .NET 1.x declarative security
 
107
                internal CustomAttributeData(Module module, ConstructorInfo constructor, object[] args, List<CustomAttributeNamedArgument> namedArguments)
 
108
                        : this(module, constructor, WrapConstructorArgs(args, constructor.MethodSignature), namedArguments)
 
109
                {
 
110
                }
 
111
 
 
112
                private static List<CustomAttributeTypedArgument> WrapConstructorArgs(object[] args, MethodSignature sig)
 
113
                {
 
114
                        List<CustomAttributeTypedArgument> list = new List<CustomAttributeTypedArgument>();
 
115
                        for (int i = 0; i < args.Length; i++)
 
116
                        {
 
117
                                list.Add(new CustomAttributeTypedArgument(sig.GetParameterType(i), args[i]));
 
118
                        }
 
119
                        return list;
 
120
                }
 
121
 
 
122
                // 4) Pseudo Custom Attribute, .NET 1.x declarative security or result of CustomAttributeBuilder.ToData()
 
123
                internal CustomAttributeData(Module module, ConstructorInfo constructor, List<CustomAttributeTypedArgument> constructorArgs, List<CustomAttributeNamedArgument> namedArguments)
 
124
                {
 
125
                        this.module = module;
 
126
                        this.customAttributeIndex = -1;
 
127
                        this.declSecurityIndex = -1;
 
128
                        this.lazyConstructor = constructor;
 
129
                        lazyConstructorArguments = constructorArgs.AsReadOnly();
 
130
                        if (namedArguments == null)
 
131
                        {
 
132
                                this.lazyNamedArguments = Empty<CustomAttributeNamedArgument>.Array;
 
133
                        }
 
134
                        else
 
135
                        {
 
136
                                this.lazyNamedArguments = namedArguments.AsReadOnly();
 
137
                        }
 
138
                }
 
139
 
 
140
                // 3) Pre-resolved Custom Attribute
 
141
                internal CustomAttributeData(Assembly asm, ConstructorInfo constructor, ByteReader br)
 
142
                {
 
143
                        this.module = asm.ManifestModule;
 
144
                        this.customAttributeIndex = -1;
 
145
                        this.declSecurityIndex = -1;
 
146
                        this.lazyConstructor = constructor;
 
147
                        if (br.Length == 0)
 
148
                        {
 
149
                                // it's legal to have an empty blob
 
150
                                lazyConstructorArguments = Empty<CustomAttributeTypedArgument>.Array;
 
151
                                lazyNamedArguments = Empty<CustomAttributeNamedArgument>.Array;
 
152
                        }
 
153
                        else
 
154
                        {
 
155
                                if (br.ReadUInt16() != 1)
 
156
                                {
 
157
                                        throw new BadImageFormatException();
 
158
                                }
 
159
                                lazyConstructorArguments = ReadConstructorArguments(asm, br, constructor);
 
160
                                lazyNamedArguments = ReadNamedArguments(asm, br, br.ReadUInt16(), constructor.DeclaringType);
 
161
                        }
 
162
                }
 
163
 
 
164
                public override string ToString()
 
165
                {
 
166
                        StringBuilder sb = new StringBuilder();
 
167
                        sb.Append('[');
 
168
                        sb.Append(Constructor.DeclaringType.FullName);
 
169
                        sb.Append('(');
 
170
                        string sep = "";
 
171
                        ParameterInfo[] parameters = Constructor.GetParameters();
 
172
                        IList<CustomAttributeTypedArgument> args = ConstructorArguments;
 
173
                        for (int i = 0; i < parameters.Length; i++)
 
174
                        {
 
175
                                sb.Append(sep);
 
176
                                sep = ", ";
 
177
                                AppendValue(sb, parameters[i].ParameterType, args[i]);
 
178
                        }
 
179
                        foreach (CustomAttributeNamedArgument named in NamedArguments)
 
180
                        {
 
181
                                sb.Append(sep);
 
182
                                sep = ", ";
 
183
                                sb.Append(named.MemberInfo.Name);
 
184
                                sb.Append(" = ");
 
185
                                FieldInfo fi = named.MemberInfo as FieldInfo;
 
186
                                Type type = fi != null ? fi.FieldType : ((PropertyInfo)named.MemberInfo).PropertyType;
 
187
                                AppendValue(sb, type, named.TypedValue);
 
188
                        }
 
189
                        sb.Append(')');
 
190
                        sb.Append(']');
 
191
                        return sb.ToString();
 
192
                }
 
193
 
 
194
                private static void AppendValue(StringBuilder sb, Type type, CustomAttributeTypedArgument arg)
 
195
                {
 
196
                        if (arg.ArgumentType == arg.ArgumentType.Module.universe.System_String)
 
197
                        {
 
198
                                sb.Append('"').Append(arg.Value).Append('"');
 
199
                        }
 
200
                        else if (arg.ArgumentType.IsArray)
 
201
                        {
 
202
                                Type elementType = arg.ArgumentType.GetElementType();
 
203
                                string elementTypeName;
 
204
                                if (elementType.IsPrimitive
 
205
                                        || elementType == type.Module.universe.System_Object
 
206
                                        || elementType == type.Module.universe.System_String
 
207
                                        || elementType == type.Module.universe.System_Type)
 
208
                                {
 
209
                                        elementTypeName = elementType.Name;
 
210
                                }
 
211
                                else
 
212
                                {
 
213
                                        elementTypeName = elementType.FullName;
 
214
                                }
 
215
                                sb.Append("new ").Append(elementTypeName).Append("[").Append(((Array)arg.Value).Length).Append("] { ");
 
216
                                string sep = "";
 
217
                                foreach (CustomAttributeTypedArgument elem in (CustomAttributeTypedArgument[])arg.Value)
 
218
                                {
 
219
                                        sb.Append(sep);
 
220
                                        sep = ", ";
 
221
                                        AppendValue(sb, elementType, elem);
 
222
                                }
 
223
                                sb.Append(" }");
 
224
                        }
 
225
                        else
 
226
                        {
 
227
                                if (arg.ArgumentType != type || (type.IsEnum && !arg.Value.Equals(0)))
 
228
                                {
 
229
                                        sb.Append('(');
 
230
                                        sb.Append(arg.ArgumentType.FullName);
 
231
                                        sb.Append(')');
 
232
                                }
 
233
                                sb.Append(arg.Value);
 
234
                        }
 
235
                }
 
236
 
 
237
                internal static void ReadDeclarativeSecurity(Module module, int index, List<CustomAttributeData> list)
 
238
                {
 
239
                        Universe u = module.universe;
 
240
                        Assembly asm = module.Assembly;
 
241
                        int action = module.DeclSecurity.records[index].Action;
 
242
                        ByteReader br = module.GetBlob(module.DeclSecurity.records[index].PermissionSet);
 
243
                        if (br.PeekByte() == '.')
 
244
                        {
 
245
                                br.ReadByte();
 
246
                                int count = br.ReadCompressedUInt();
 
247
                                for (int j = 0; j < count; j++)
 
248
                                {
 
249
                                        Type type = ReadType(asm, br);
 
250
                                        ConstructorInfo constructor = type.GetPseudoCustomAttributeConstructor(u.System_Security_Permissions_SecurityAction);
 
251
                                        // LAMESPEC there is an additional length here (probably of the named argument list)
 
252
                                        byte[] blob = br.ReadBytes(br.ReadCompressedUInt());
 
253
                                        list.Add(new CustomAttributeData(asm, constructor, action, blob, index));
 
254
                                }
 
255
                        }
 
256
                        else
 
257
                        {
 
258
                                // .NET 1.x format (xml)
 
259
                                char[] buf = new char[br.Length / 2];
 
260
                                for (int i = 0; i < buf.Length; i++)
 
261
                                {
 
262
                                        buf[i] = br.ReadChar();
 
263
                                }
 
264
                                string xml = new String(buf);
 
265
                                ConstructorInfo constructor = u.System_Security_Permissions_PermissionSetAttribute.GetPseudoCustomAttributeConstructor(u.System_Security_Permissions_SecurityAction);
 
266
                                List<CustomAttributeNamedArgument> args = new List<CustomAttributeNamedArgument>();
 
267
                                args.Add(new CustomAttributeNamedArgument(GetProperty(u.System_Security_Permissions_PermissionSetAttribute, "XML", u.System_String),
 
268
                                        new CustomAttributeTypedArgument(u.System_String, xml)));
 
269
                                list.Add(new CustomAttributeData(asm.ManifestModule, constructor, new object[] { action }, args));
 
270
                        }
 
271
                }
 
272
 
 
273
                // 5) Unresolved declarative security
 
274
                internal CustomAttributeData(Assembly asm, ConstructorInfo constructor, int securityAction, byte[] blob, int index)
 
275
                {
 
276
                        this.module = asm.ManifestModule;
 
277
                        this.customAttributeIndex = -1;
 
278
                        this.declSecurityIndex = index;
 
279
                        Universe u = constructor.Module.universe;
 
280
                        this.lazyConstructor = constructor;
 
281
                        List<CustomAttributeTypedArgument> list = new List<CustomAttributeTypedArgument>();
 
282
                        list.Add(new CustomAttributeTypedArgument(u.System_Security_Permissions_SecurityAction, securityAction));
 
283
                        this.lazyConstructorArguments =  list.AsReadOnly();
 
284
                        this.declSecurityBlob = blob;
 
285
                }
 
286
 
 
287
                private static Type ReadFieldOrPropType(Assembly asm, ByteReader br)
 
288
                {
 
289
                        Universe u = asm.universe;
 
290
                        switch (br.ReadByte())
 
291
                        {
 
292
                                case Signature.ELEMENT_TYPE_BOOLEAN:
 
293
                                        return u.System_Boolean;
 
294
                                case Signature.ELEMENT_TYPE_CHAR:
 
295
                                        return u.System_Char;
 
296
                                case Signature.ELEMENT_TYPE_I1:
 
297
                                        return u.System_SByte;
 
298
                                case Signature.ELEMENT_TYPE_U1:
 
299
                                        return u.System_Byte;
 
300
                                case Signature.ELEMENT_TYPE_I2:
 
301
                                        return u.System_Int16;
 
302
                                case Signature.ELEMENT_TYPE_U2:
 
303
                                        return u.System_UInt16;
 
304
                                case Signature.ELEMENT_TYPE_I4:
 
305
                                        return u.System_Int32;
 
306
                                case Signature.ELEMENT_TYPE_U4:
 
307
                                        return u.System_UInt32;
 
308
                                case Signature.ELEMENT_TYPE_I8:
 
309
                                        return u.System_Int64;
 
310
                                case Signature.ELEMENT_TYPE_U8:
 
311
                                        return u.System_UInt64;
 
312
                                case Signature.ELEMENT_TYPE_R4:
 
313
                                        return u.System_Single;
 
314
                                case Signature.ELEMENT_TYPE_R8:
 
315
                                        return u.System_Double;
 
316
                                case Signature.ELEMENT_TYPE_STRING:
 
317
                                        return u.System_String;
 
318
                                case Signature.ELEMENT_TYPE_SZARRAY:
 
319
                                        return ReadFieldOrPropType(asm, br).MakeArrayType();
 
320
                                case 0x55:
 
321
                                        return ReadType(asm, br);
 
322
                                case 0x50:
 
323
                                        return u.System_Type;
 
324
                                case 0x51:
 
325
                                        return u.System_Object;
 
326
                                default:
 
327
                                        throw new BadImageFormatException();
 
328
                        }
 
329
                }
 
330
 
 
331
                private static CustomAttributeTypedArgument ReadFixedArg(Assembly asm, ByteReader br, Type type)
 
332
                {
 
333
                        Universe u = asm.universe;
 
334
                        if (type == u.System_String)
 
335
                        {
 
336
                                return new CustomAttributeTypedArgument(type, br.ReadString());
 
337
                        }
 
338
                        else if (type == u.System_Boolean)
 
339
                        {
 
340
                                return new CustomAttributeTypedArgument(type, br.ReadByte() != 0);
 
341
                        }
 
342
                        else if (type == u.System_Char)
 
343
                        {
 
344
                                return new CustomAttributeTypedArgument(type, br.ReadChar());
 
345
                        }
 
346
                        else if (type == u.System_Single)
 
347
                        {
 
348
                                return new CustomAttributeTypedArgument(type, br.ReadSingle());
 
349
                        }
 
350
                        else if (type == u.System_Double)
 
351
                        {
 
352
                                return new CustomAttributeTypedArgument(type, br.ReadDouble());
 
353
                        }
 
354
                        else if (type == u.System_SByte)
 
355
                        {
 
356
                                return new CustomAttributeTypedArgument(type, br.ReadSByte());
 
357
                        }
 
358
                        else if (type == u.System_Int16)
 
359
                        {
 
360
                                return new CustomAttributeTypedArgument(type, br.ReadInt16());
 
361
                        }
 
362
                        else if (type == u.System_Int32)
 
363
                        {
 
364
                                return new CustomAttributeTypedArgument(type, br.ReadInt32());
 
365
                        }
 
366
                        else if (type == u.System_Int64)
 
367
                        {
 
368
                                return new CustomAttributeTypedArgument(type, br.ReadInt64());
 
369
                        }
 
370
                        else if (type == u.System_Byte)
 
371
                        {
 
372
                                return new CustomAttributeTypedArgument(type, br.ReadByte());
 
373
                        }
 
374
                        else if (type == u.System_UInt16)
 
375
                        {
 
376
                                return new CustomAttributeTypedArgument(type, br.ReadUInt16());
 
377
                        }
 
378
                        else if (type == u.System_UInt32)
 
379
                        {
 
380
                                return new CustomAttributeTypedArgument(type, br.ReadUInt32());
 
381
                        }
 
382
                        else if (type == u.System_UInt64)
 
383
                        {
 
384
                                return new CustomAttributeTypedArgument(type, br.ReadUInt64());
 
385
                        }
 
386
                        else if (type == u.System_Type)
 
387
                        {
 
388
                                return new CustomAttributeTypedArgument(type, ReadType(asm, br));
 
389
                        }
 
390
                        else if (type == u.System_Object)
 
391
                        {
 
392
                                return ReadFixedArg(asm, br, ReadFieldOrPropType(asm, br));
 
393
                        }
 
394
                        else if (type.IsArray)
 
395
                        {
 
396
                                int length = br.ReadInt32();
 
397
                                if (length == -1)
 
398
                                {
 
399
                                        return new CustomAttributeTypedArgument(type, null);
 
400
                                }
 
401
                                Type elementType = type.GetElementType();
 
402
                                CustomAttributeTypedArgument[] array = new CustomAttributeTypedArgument[length];
 
403
                                for (int i = 0; i < length; i++)
 
404
                                {
 
405
                                        array[i] = ReadFixedArg(asm, br, elementType);
 
406
                                }
 
407
                                return new CustomAttributeTypedArgument(type, array);
 
408
                        }
 
409
                        else if (type.IsEnum)
 
410
                        {
 
411
                                return new CustomAttributeTypedArgument(type, ReadFixedArg(asm, br, type.GetEnumUnderlyingTypeImpl()).Value);
 
412
                        }
 
413
                        else
 
414
                        {
 
415
                                throw new InvalidOperationException();
 
416
                        }
 
417
                }
 
418
 
 
419
                private static Type ReadType(Assembly asm, ByteReader br)
 
420
                {
 
421
                        string typeName = br.ReadString();
 
422
                        if (typeName == null)
 
423
                        {
 
424
                                return null;
 
425
                        }
 
426
                        if (typeName.Length > 0 && typeName[typeName.Length - 1] == 0)
 
427
                        {
 
428
                                // there are broken compilers that emit an extra NUL character after the type name
 
429
                                typeName = typeName.Substring(0, typeName.Length - 1);
 
430
                        }
 
431
                        return TypeNameParser.Parse(typeName, true).GetType(asm.universe, asm, true, typeName, true, false);
 
432
                }
 
433
 
 
434
                private static IList<CustomAttributeTypedArgument> ReadConstructorArguments(Assembly asm, ByteReader br, ConstructorInfo constructor)
 
435
                {
 
436
                        MethodSignature sig = constructor.MethodSignature;
 
437
                        int count = sig.GetParameterCount();
 
438
                        List<CustomAttributeTypedArgument> list = new List<CustomAttributeTypedArgument>(count);
 
439
                        for (int i = 0; i < count; i++)
 
440
                        {
 
441
                                list.Add(ReadFixedArg(asm, br, sig.GetParameterType(i)));
 
442
                        }
 
443
                        return list.AsReadOnly();
 
444
                }
 
445
 
 
446
                private static IList<CustomAttributeNamedArgument> ReadNamedArguments(Assembly asm, ByteReader br, int named, Type type)
 
447
                {
 
448
                        List<CustomAttributeNamedArgument> list = new List<CustomAttributeNamedArgument>(named);
 
449
                        for (int i = 0; i < named; i++)
 
450
                        {
 
451
                                byte fieldOrProperty = br.ReadByte();
 
452
                                Type fieldOrPropertyType = ReadFieldOrPropType(asm, br);
 
453
                                string name = br.ReadString();
 
454
                                CustomAttributeTypedArgument value = ReadFixedArg(asm, br, fieldOrPropertyType);
 
455
                                MemberInfo member;
 
456
                                switch (fieldOrProperty)
 
457
                                {
 
458
                                        case 0x53:
 
459
                                                member = GetField(type, name, fieldOrPropertyType);
 
460
                                                break;
 
461
                                        case 0x54:
 
462
                                                member = GetProperty(type, name, fieldOrPropertyType);
 
463
                                                break;
 
464
                                        default:
 
465
                                                throw new BadImageFormatException();
 
466
                                }
 
467
                                list.Add(new CustomAttributeNamedArgument(member, value));
 
468
                        }
 
469
                        return list.AsReadOnly();
 
470
                }
 
471
 
 
472
                private static FieldInfo GetField(Type type, string name, Type fieldType)
 
473
                {
 
474
                        Type org = type;
 
475
                        for (; type != null && !type.__IsMissing; type = type.BaseType)
 
476
                        {
 
477
                                foreach (FieldInfo field in type.__GetDeclaredFields())
 
478
                                {
 
479
                                        if (field.IsPublic && !field.IsStatic && field.Name == name)
 
480
                                        {
 
481
                                                return field;
 
482
                                        }
 
483
                                }
 
484
                        }
 
485
                        // if the field is missing, we stick the missing field on the first missing base type
 
486
                        if (type == null)
 
487
                        {
 
488
                                type = org;
 
489
                        }
 
490
                        FieldSignature sig = FieldSignature.Create(fieldType, new CustomModifiers());
 
491
                        return type.FindField(name, sig)
 
492
                                ?? type.Module.universe.GetMissingFieldOrThrow(type, name, sig);
 
493
                }
 
494
 
 
495
                private static PropertyInfo GetProperty(Type type, string name, Type propertyType)
 
496
                {
 
497
                        Type org = type;
 
498
                        for (; type != null && !type.__IsMissing; type = type.BaseType)
 
499
                        {
 
500
                                foreach (PropertyInfo property in type.__GetDeclaredProperties())
 
501
                                {
 
502
                                        if (property.IsPublic && !property.IsStatic && property.Name == name)
 
503
                                        {
 
504
                                                return property;
 
505
                                        }
 
506
                                }
 
507
                        }
 
508
                        // if the property is missing, we stick the missing property on the first missing base type
 
509
                        if (type == null)
 
510
                        {
 
511
                                type = org;
 
512
                        }
 
513
                        return type.Module.universe.GetMissingPropertyOrThrow(type, name, PropertySignature.Create(CallingConventions.Standard | CallingConventions.HasThis, propertyType, null, new PackedCustomModifiers()));
 
514
                }
 
515
 
 
516
                [Obsolete("Use AttributeType property instead.")]
 
517
                internal bool __TryReadTypeName(out string ns, out string name)
 
518
                {
 
519
                        if (Constructor.DeclaringType.IsNested)
 
520
                        {
 
521
                                ns = null;
 
522
                                name = null;
 
523
                                return false;
 
524
                        }
 
525
                        ns = Constructor.DeclaringType.__Namespace;
 
526
                        name = Constructor.DeclaringType.__Name;
 
527
                        return true;
 
528
                }
 
529
 
 
530
                public byte[] __GetBlob()
 
531
                {
 
532
                        if (declSecurityBlob != null)
 
533
                        {
 
534
                                return (byte[])declSecurityBlob.Clone();
 
535
                        }
 
536
                        else if (customAttributeIndex == -1)
 
537
                        {
 
538
                                return __ToBuilder().GetBlob(module.Assembly);
 
539
                        }
 
540
                        else
 
541
                        {
 
542
                                return ((ModuleReader)module).GetBlobCopy(module.CustomAttribute.records[customAttributeIndex].Value);
 
543
                        }
 
544
                }
 
545
 
 
546
                public int __Parent
 
547
                {
 
548
                        get
 
549
                        {
 
550
                                return customAttributeIndex >= 0
 
551
                                        ? module.CustomAttribute.records[customAttributeIndex].Parent
 
552
                                        : declSecurityIndex >= 0
 
553
                                                ? module.DeclSecurity.records[declSecurityIndex].Parent
 
554
                                                : 0;
 
555
                        }
 
556
                }
 
557
 
 
558
                // .NET 4.5 API
 
559
                public Type AttributeType
 
560
                {
 
561
                        get { return Constructor.DeclaringType; }
 
562
                }
 
563
 
 
564
                public ConstructorInfo Constructor
 
565
                {
 
566
                        get
 
567
                        {
 
568
                                if (lazyConstructor == null)
 
569
                                {
 
570
                                        lazyConstructor = (ConstructorInfo)module.ResolveMethod(module.CustomAttribute.records[customAttributeIndex].Type);
 
571
                                }
 
572
                                return lazyConstructor;
 
573
                        }
 
574
                }
 
575
 
 
576
                public IList<CustomAttributeTypedArgument> ConstructorArguments
 
577
                {
 
578
                        get
 
579
                        {
 
580
                                if (lazyConstructorArguments == null)
 
581
                                {
 
582
                                        LazyParseArguments();
 
583
                                }
 
584
                                return lazyConstructorArguments;
 
585
                        }
 
586
                }
 
587
 
 
588
                public IList<CustomAttributeNamedArgument> NamedArguments
 
589
                {
 
590
                        get
 
591
                        {
 
592
                                if (lazyNamedArguments == null)
 
593
                                {
 
594
                                        if (customAttributeIndex >= 0)
 
595
                                        {
 
596
                                                // 1) Unresolved Custom Attribute
 
597
                                                LazyParseArguments();
 
598
                                        }
 
599
                                        else
 
600
                                        {
 
601
                                                // 5) Unresolved declarative security
 
602
                                                ByteReader br = new ByteReader(declSecurityBlob, 0, declSecurityBlob.Length);
 
603
                                                // LAMESPEC the count of named arguments is a compressed integer (instead of UInt16 as NumNamed in custom attributes)
 
604
                                                lazyNamedArguments = ReadNamedArguments(module.Assembly, br, br.ReadCompressedUInt(), Constructor.DeclaringType);
 
605
                                        }
 
606
                                }
 
607
                                return lazyNamedArguments;
 
608
                        }
 
609
                }
 
610
 
 
611
                private void LazyParseArguments()
 
612
                {
 
613
                        ByteReader br = module.GetBlob(module.CustomAttribute.records[customAttributeIndex].Value);
 
614
                        if (br.Length == 0)
 
615
                        {
 
616
                                // it's legal to have an empty blob
 
617
                                lazyConstructorArguments = Empty<CustomAttributeTypedArgument>.Array;
 
618
                                lazyNamedArguments = Empty<CustomAttributeNamedArgument>.Array;
 
619
                        }
 
620
                        else
 
621
                        {
 
622
                                if (br.ReadUInt16() != 1)
 
623
                                {
 
624
                                        throw new BadImageFormatException();
 
625
                                }
 
626
                                lazyConstructorArguments = ReadConstructorArguments(module.Assembly, br, Constructor);
 
627
                                lazyNamedArguments = ReadNamedArguments(module.Assembly, br, br.ReadUInt16(), Constructor.DeclaringType);
 
628
                        }
 
629
                }
 
630
 
 
631
                public CustomAttributeBuilder __ToBuilder()
 
632
                {
 
633
                        ParameterInfo[] parameters = Constructor.GetParameters();
 
634
                        object[] args = new object[ConstructorArguments.Count];
 
635
                        for (int i = 0; i < args.Length; i++)
 
636
                        {
 
637
                                args[i] = RewrapArray(parameters[i].ParameterType, ConstructorArguments[i]);
 
638
                        }
 
639
                        List<PropertyInfo> namedProperties = new List<PropertyInfo>();
 
640
                        List<object> propertyValues = new List<object>();
 
641
                        List<FieldInfo> namedFields = new List<FieldInfo>();
 
642
                        List<object> fieldValues = new List<object>();
 
643
                        foreach (CustomAttributeNamedArgument named in NamedArguments)
 
644
                        {
 
645
                                PropertyInfo pi = named.MemberInfo as PropertyInfo;
 
646
                                if (pi != null)
 
647
                                {
 
648
                                        namedProperties.Add(pi);
 
649
                                        propertyValues.Add(RewrapArray(pi.PropertyType, named.TypedValue));
 
650
                                }
 
651
                                else
 
652
                                {
 
653
                                        FieldInfo fi = (FieldInfo)named.MemberInfo;
 
654
                                        namedFields.Add(fi);
 
655
                                        fieldValues.Add(RewrapArray(fi.FieldType, named.TypedValue));
 
656
                                }
 
657
                        }
 
658
                        return new CustomAttributeBuilder(Constructor, args, namedProperties.ToArray(), propertyValues.ToArray(), namedFields.ToArray(), fieldValues.ToArray());
 
659
                }
 
660
 
 
661
                private static object RewrapArray(Type type, CustomAttributeTypedArgument arg)
 
662
                {
 
663
                        IList<CustomAttributeTypedArgument> list = arg.Value as IList<CustomAttributeTypedArgument>;
 
664
                        if (list != null)
 
665
                        {
 
666
                                Type elementType = arg.ArgumentType.GetElementType();
 
667
                                object[] arr = new object[list.Count];
 
668
                                for (int i = 0; i < arr.Length; i++)
 
669
                                {
 
670
                                        arr[i] = RewrapArray(elementType, list[i]);
 
671
                                }
 
672
                                if (type == type.Module.universe.System_Object)
 
673
                                {
 
674
                                        return CustomAttributeBuilder.__MakeTypedArgument(arg.ArgumentType, arr);
 
675
                                }
 
676
                                return arr;
 
677
                        }
 
678
                        else
 
679
                        {
 
680
                                return arg.Value;
 
681
                        }
 
682
                }
 
683
 
 
684
                public static IList<CustomAttributeData> GetCustomAttributes(MemberInfo member)
 
685
                {
 
686
                        return __GetCustomAttributes(member, null, false);
 
687
                }
 
688
 
 
689
                public static IList<CustomAttributeData> GetCustomAttributes(Assembly assembly)
 
690
                {
 
691
                        return assembly.GetCustomAttributesData(null);
 
692
                }
 
693
 
 
694
                public static IList<CustomAttributeData> GetCustomAttributes(Module module)
 
695
                {
 
696
                        return __GetCustomAttributes(module, null, false);
 
697
                }
 
698
 
 
699
                public static IList<CustomAttributeData> GetCustomAttributes(ParameterInfo parameter)
 
700
                {
 
701
                        return __GetCustomAttributes(parameter, null, false);
 
702
                }
 
703
 
 
704
                public static IList<CustomAttributeData> __GetCustomAttributes(Assembly assembly, Type attributeType, bool inherit)
 
705
                {
 
706
                        return assembly.GetCustomAttributesData(attributeType);
 
707
                }
 
708
 
 
709
                public static IList<CustomAttributeData> __GetCustomAttributes(Module module, Type attributeType, bool inherit)
 
710
                {
 
711
                        if (module.__IsMissing)
 
712
                        {
 
713
                                throw new MissingModuleException((MissingModule)module);
 
714
                        }
 
715
                        return GetCustomAttributesImpl(null, module, 0x00000001, attributeType) ?? EmptyList;
 
716
                }
 
717
 
 
718
                public static IList<CustomAttributeData> __GetCustomAttributes(ParameterInfo parameter, Type attributeType, bool inherit)
 
719
                {
 
720
                        Module module = parameter.Module;
 
721
                        List<CustomAttributeData> list = null;
 
722
                        if (module.universe.ReturnPseudoCustomAttributes)
 
723
                        {
 
724
                                if (attributeType == null || attributeType.IsAssignableFrom(parameter.Module.universe.System_Runtime_InteropServices_MarshalAsAttribute))
 
725
                                {
 
726
                                        FieldMarshal spec;
 
727
                                        if (parameter.__TryGetFieldMarshal(out spec))
 
728
                                        {
 
729
                                                if (list == null)
 
730
                                                {
 
731
                                                        list = new List<CustomAttributeData>();
 
732
                                                }
 
733
                                                list.Add(CustomAttributeData.CreateMarshalAsPseudoCustomAttribute(parameter.Module, spec));
 
734
                                        }
 
735
                                }
 
736
                        }
 
737
                        ModuleBuilder mb = module as ModuleBuilder;
 
738
                        int token = parameter.MetadataToken;
 
739
                        if (mb != null && mb.IsSaved && ModuleBuilder.IsPseudoToken(token))
 
740
                        {
 
741
                                token = mb.ResolvePseudoToken(token);
 
742
                        }
 
743
                        return GetCustomAttributesImpl(list, module, token, attributeType) ?? EmptyList;
 
744
                }
 
745
 
 
746
                public static IList<CustomAttributeData> __GetCustomAttributes(MemberInfo member, Type attributeType, bool inherit)
 
747
                {
 
748
                        if (!member.IsBaked)
 
749
                        {
 
750
                                // like .NET we we don't return custom attributes for unbaked members
 
751
                                throw new NotImplementedException();
 
752
                        }
 
753
                        if (!inherit || !IsInheritableAttribute(attributeType))
 
754
                        {
 
755
                                return GetCustomAttributesImpl(null, member, attributeType) ?? EmptyList;
 
756
                        }
 
757
                        List<CustomAttributeData> list = new List<CustomAttributeData>();
 
758
                        for (; ; )
 
759
                        {
 
760
                                GetCustomAttributesImpl(list, member, attributeType);
 
761
                                Type type = member as Type;
 
762
                                if (type != null)
 
763
                                {
 
764
                                        type = type.BaseType;
 
765
                                        if (type == null)
 
766
                                        {
 
767
                                                return list;
 
768
                                        }
 
769
                                        member = type;
 
770
                                        continue;
 
771
                                }
 
772
                                MethodInfo method = member as MethodInfo;
 
773
                                if (method != null)
 
774
                                {
 
775
                                        MemberInfo prev = member;
 
776
                                        method = method.GetBaseDefinition();
 
777
                                        if (method == null || method == prev)
 
778
                                        {
 
779
                                                return list;
 
780
                                        }
 
781
                                        member = method;
 
782
                                        continue;
 
783
                                }
 
784
                                return list;
 
785
                        }
 
786
                }
 
787
 
 
788
                private static List<CustomAttributeData> GetCustomAttributesImpl(List<CustomAttributeData> list, MemberInfo member, Type attributeType)
 
789
                {
 
790
                        if (member.Module.universe.ReturnPseudoCustomAttributes)
 
791
                        {
 
792
                                List<CustomAttributeData> pseudo = member.GetPseudoCustomAttributes(attributeType);
 
793
                                if (list == null)
 
794
                                {
 
795
                                        list = pseudo;
 
796
                                }
 
797
                                else if (pseudo != null)
 
798
                                {
 
799
                                        list.AddRange(pseudo);
 
800
                                }
 
801
                        }
 
802
                        return GetCustomAttributesImpl(list, member.Module, member.GetCurrentToken(), attributeType);
 
803
                }
 
804
 
 
805
                internal static List<CustomAttributeData> GetCustomAttributesImpl(List<CustomAttributeData> list, Module module, int token, Type attributeType)
 
806
                {
 
807
                        foreach (int i in module.CustomAttribute.Filter(token))
 
808
                        {
 
809
                                if (attributeType == null)
 
810
                                {
 
811
                                        if (list == null)
 
812
                                        {
 
813
                                                list = new List<CustomAttributeData>();
 
814
                                        }
 
815
                                        list.Add(new CustomAttributeData(module, i));
 
816
                                }
 
817
                                else
 
818
                                {
 
819
                                        if (attributeType.IsAssignableFrom(module.ResolveMethod(module.CustomAttribute.records[i].Type).DeclaringType))
 
820
                                        {
 
821
                                                if (list == null)
 
822
                                                {
 
823
                                                        list = new List<CustomAttributeData>();
 
824
                                                }
 
825
                                                list.Add(new CustomAttributeData(module, i));
 
826
                                        }
 
827
                                }
 
828
                        }
 
829
                        return list;
 
830
                }
 
831
 
 
832
                public static IList<CustomAttributeData> __GetCustomAttributes(Type type, Type interfaceType, Type attributeType, bool inherit)
 
833
                {
 
834
                        Module module = type.Module;
 
835
                        foreach (int i in module.InterfaceImpl.Filter(type.MetadataToken))
 
836
                        {
 
837
                                if (module.ResolveType(module.InterfaceImpl.records[i].Interface, type) == interfaceType)
 
838
                                {
 
839
                                        return GetCustomAttributesImpl(null, module, (InterfaceImplTable.Index << 24) | (i + 1), attributeType) ?? EmptyList;
 
840
                                }
 
841
                        }
 
842
                        return EmptyList;
 
843
                }
 
844
 
 
845
                public static IList<CustomAttributeData> __GetDeclarativeSecurity(Assembly assembly)
 
846
                {
 
847
                        if (assembly.__IsMissing)
 
848
                        {
 
849
                                throw new MissingAssemblyException((MissingAssembly)assembly);
 
850
                        }
 
851
                        return assembly.ManifestModule.GetDeclarativeSecurity(0x20000001);
 
852
                }
 
853
 
 
854
                public static IList<CustomAttributeData> __GetDeclarativeSecurity(Type type)
 
855
                {
 
856
                        if ((type.Attributes & TypeAttributes.HasSecurity) != 0)
 
857
                        {
 
858
                                return type.Module.GetDeclarativeSecurity(type.MetadataToken);
 
859
                        }
 
860
                        else
 
861
                        {
 
862
                                return EmptyList;
 
863
                        }
 
864
                }
 
865
 
 
866
                public static IList<CustomAttributeData> __GetDeclarativeSecurity(MethodBase method)
 
867
                {
 
868
                        if ((method.Attributes & MethodAttributes.HasSecurity) != 0)
 
869
                        {
 
870
                                return method.Module.GetDeclarativeSecurity(method.MetadataToken);
 
871
                        }
 
872
                        else
 
873
                        {
 
874
                                return EmptyList;
 
875
                        }
 
876
                }
 
877
 
 
878
                private static bool IsInheritableAttribute(Type attribute)
 
879
                {
 
880
                        Type attributeUsageAttribute = attribute.Module.universe.System_AttributeUsageAttribute;
 
881
                        IList<CustomAttributeData> attr = __GetCustomAttributes(attribute, attributeUsageAttribute, false);
 
882
                        if (attr.Count != 0)
 
883
                        {
 
884
                                foreach (CustomAttributeNamedArgument named in attr[0].NamedArguments)
 
885
                                {
 
886
                                        if (named.MemberInfo.Name == "Inherited")
 
887
                                        {
 
888
                                                return (bool)named.TypedValue.Value;
 
889
                                        }
 
890
                                }
 
891
                        }
 
892
                        return true;
 
893
                }
 
894
 
 
895
                internal static CustomAttributeData CreateDllImportPseudoCustomAttribute(Module module, ImplMapFlags flags, string entryPoint, string dllName, MethodImplAttributes attr)
 
896
                {
 
897
                        Type type = module.universe.System_Runtime_InteropServices_DllImportAttribute;
 
898
                        ConstructorInfo constructor = type.GetPseudoCustomAttributeConstructor(module.universe.System_String);
 
899
                        List<CustomAttributeNamedArgument> list = new List<CustomAttributeNamedArgument>();
 
900
                        System.Runtime.InteropServices.CharSet charSet;
 
901
                        switch (flags & ImplMapFlags.CharSetMask)
 
902
                        {
 
903
                                case ImplMapFlags.CharSetAnsi:
 
904
                                        charSet = System.Runtime.InteropServices.CharSet.Ansi;
 
905
                                        break;
 
906
                                case ImplMapFlags.CharSetUnicode:
 
907
                                        charSet = System.Runtime.InteropServices.CharSet.Unicode;
 
908
                                        break;
 
909
                                case ImplMapFlags.CharSetAuto:
 
910
                                        charSet = System.Runtime.InteropServices.CharSet.Auto;
 
911
                                        break;
 
912
                                case ImplMapFlags.CharSetNotSpec:
 
913
                                default:
 
914
                                        charSet = System.Runtime.InteropServices.CharSet.None;
 
915
                                        break;
 
916
                        }
 
917
                        System.Runtime.InteropServices.CallingConvention callingConvention;
 
918
                        switch (flags & ImplMapFlags.CallConvMask)
 
919
                        {
 
920
                                case ImplMapFlags.CallConvCdecl:
 
921
                                        callingConvention = System.Runtime.InteropServices.CallingConvention.Cdecl;
 
922
                                        break;
 
923
                                case ImplMapFlags.CallConvFastcall:
 
924
                                        callingConvention = System.Runtime.InteropServices.CallingConvention.FastCall;
 
925
                                        break;
 
926
                                case ImplMapFlags.CallConvStdcall:
 
927
                                        callingConvention = System.Runtime.InteropServices.CallingConvention.StdCall;
 
928
                                        break;
 
929
                                case ImplMapFlags.CallConvThiscall:
 
930
                                        callingConvention = System.Runtime.InteropServices.CallingConvention.ThisCall;
 
931
                                        break;
 
932
                                case ImplMapFlags.CallConvWinapi:
 
933
                                        callingConvention = System.Runtime.InteropServices.CallingConvention.Winapi;
 
934
                                        break;
 
935
                                default:
 
936
                                        callingConvention = 0;
 
937
                                        break;
 
938
                        }
 
939
                        AddNamedArgument(list, type, "EntryPoint", entryPoint);
 
940
                        AddNamedArgument(list, type, "CharSet", module.universe.System_Runtime_InteropServices_CharSet, (int)charSet);
 
941
                        AddNamedArgument(list, type, "ExactSpelling", (int)flags, (int)ImplMapFlags.NoMangle);
 
942
                        AddNamedArgument(list, type, "SetLastError", (int)flags, (int)ImplMapFlags.SupportsLastError);
 
943
                        AddNamedArgument(list, type, "PreserveSig", (int)attr, (int)MethodImplAttributes.PreserveSig);
 
944
                        AddNamedArgument(list, type, "CallingConvention", module.universe.System_Runtime_InteropServices_CallingConvention, (int)callingConvention);
 
945
                        AddNamedArgument(list, type, "BestFitMapping", (int)flags, (int)ImplMapFlags.BestFitOn);
 
946
                        AddNamedArgument(list, type, "ThrowOnUnmappableChar", (int)flags, (int)ImplMapFlags.CharMapErrorOn);
 
947
                        return new CustomAttributeData(module, constructor, new object[] { dllName }, list);
 
948
                }
 
949
 
 
950
                internal static CustomAttributeData CreateMarshalAsPseudoCustomAttribute(Module module, FieldMarshal fm)
 
951
                {
 
952
                        Type typeofMarshalAs = module.universe.System_Runtime_InteropServices_MarshalAsAttribute;
 
953
                        Type typeofUnmanagedType = module.universe.System_Runtime_InteropServices_UnmanagedType;
 
954
                        Type typeofVarEnum = module.universe.System_Runtime_InteropServices_VarEnum;
 
955
                        Type typeofType = module.universe.System_Type;
 
956
                        List<CustomAttributeNamedArgument> named = new List<CustomAttributeNamedArgument>();
 
957
                        AddNamedArgument(named, typeofMarshalAs, "ArraySubType", typeofUnmanagedType, (int)(fm.ArraySubType ?? 0));
 
958
                        AddNamedArgument(named, typeofMarshalAs, "SizeParamIndex", module.universe.System_Int16, fm.SizeParamIndex ?? 0);
 
959
                        AddNamedArgument(named, typeofMarshalAs, "SizeConst", module.universe.System_Int32, fm.SizeConst ?? 0);
 
960
                        AddNamedArgument(named, typeofMarshalAs, "IidParameterIndex", module.universe.System_Int32, fm.IidParameterIndex ?? 0);
 
961
                        AddNamedArgument(named, typeofMarshalAs, "SafeArraySubType", typeofVarEnum, (int)(fm.SafeArraySubType ?? 0));
 
962
                        if (fm.SafeArrayUserDefinedSubType != null)
 
963
                        {
 
964
                                AddNamedArgument(named, typeofMarshalAs, "SafeArrayUserDefinedSubType", typeofType, fm.SafeArrayUserDefinedSubType);
 
965
                        }
 
966
                        if (fm.MarshalType != null)
 
967
                        {
 
968
                                AddNamedArgument(named, typeofMarshalAs, "MarshalType", module.universe.System_String, fm.MarshalType);
 
969
                        }
 
970
                        if (fm.MarshalTypeRef != null)
 
971
                        {
 
972
                                AddNamedArgument(named, typeofMarshalAs, "MarshalTypeRef", module.universe.System_Type, fm.MarshalTypeRef);
 
973
                        }
 
974
                        if (fm.MarshalCookie != null)
 
975
                        {
 
976
                                AddNamedArgument(named, typeofMarshalAs, "MarshalCookie", module.universe.System_String, fm.MarshalCookie);
 
977
                        }
 
978
                        ConstructorInfo constructor = typeofMarshalAs.GetPseudoCustomAttributeConstructor(typeofUnmanagedType);
 
979
                        return new CustomAttributeData(module, constructor, new object[] { (int)fm.UnmanagedType }, named);
 
980
                }
 
981
 
 
982
                private static void AddNamedArgument(List<CustomAttributeNamedArgument> list, Type type, string fieldName, string value)
 
983
                {
 
984
                        AddNamedArgument(list, type, fieldName, type.Module.universe.System_String, value);
 
985
                }
 
986
 
 
987
                private static void AddNamedArgument(List<CustomAttributeNamedArgument> list, Type type, string fieldName, int flags, int flagMask)
 
988
                {
 
989
                        AddNamedArgument(list, type, fieldName, type.Module.universe.System_Boolean, (flags & flagMask) != 0);
 
990
                }
 
991
 
 
992
                private static void AddNamedArgument(List<CustomAttributeNamedArgument> list, Type attributeType, string fieldName, Type valueType, object value)
 
993
                {
 
994
                        // some fields are not available on the .NET Compact Framework version of DllImportAttribute/MarshalAsAttribute
 
995
                        FieldInfo field = attributeType.FindField(fieldName, FieldSignature.Create(valueType, new CustomModifiers()));
 
996
                        if (field != null)
 
997
                        {
 
998
                                list.Add(new CustomAttributeNamedArgument(field, new CustomAttributeTypedArgument(valueType, value)));
 
999
                        }
 
1000
                }
 
1001
 
 
1002
                internal static CustomAttributeData CreateFieldOffsetPseudoCustomAttribute(Module module, int offset)
 
1003
                {
 
1004
                        Type type = module.universe.System_Runtime_InteropServices_FieldOffsetAttribute;
 
1005
                        ConstructorInfo constructor = type.GetPseudoCustomAttributeConstructor(module.universe.System_Int32);
 
1006
                        return new CustomAttributeData(module, constructor, new object[] { offset }, null);
 
1007
                }
 
1008
 
 
1009
                internal static CustomAttributeData CreatePreserveSigPseudoCustomAttribute(Module module)
 
1010
                {
 
1011
                        Type type = module.universe.System_Runtime_InteropServices_PreserveSigAttribute;
 
1012
                        ConstructorInfo constructor = type.GetPseudoCustomAttributeConstructor();
 
1013
                        return new CustomAttributeData(module, constructor, Empty<object>.Array, null);
 
1014
                }
 
1015
        }
 
1016
}