2 // import.cs: System.Reflection conversions
4 // Authors: Marek Safar (marek.safar@gmail.com)
6 // Dual licensed under the terms of the MIT X11 or GNU GPL
8 // Copyright 2009, 2010 Novell, Inc
12 using System
.Reflection
;
13 using System
.Runtime
.CompilerServices
;
15 using System
.Collections
.Generic
;
16 using System
.Diagnostics
;
17 using System
.Runtime
.InteropServices
;
21 public static class Import
23 static Dictionary
<Type
, TypeSpec
> import_cache
;
24 static Dictionary
<Type
, PredefinedTypeSpec
> type_2_predefined
;
26 public static void Initialize ()
28 import_cache
= new Dictionary
<Type
, TypeSpec
> (1024, ReferenceEquality
<Type
>.Default
);
30 // Setup mapping for predefined types
31 type_2_predefined
= new Dictionary
<Type
, PredefinedTypeSpec
> () {
32 { typeof (object), TypeManager.object_type }
,
33 { typeof (System.ValueType), TypeManager.value_type }
,
34 { typeof (System.Attribute), TypeManager.attribute_type }
,
36 { typeof (int), TypeManager.int32_type }
,
37 { typeof (long), TypeManager.int64_type }
,
38 { typeof (uint), TypeManager.uint32_type }
,
39 { typeof (ulong), TypeManager.uint64_type }
,
40 { typeof (byte), TypeManager.byte_type }
,
41 { typeof (sbyte), TypeManager.sbyte_type }
,
42 { typeof (short), TypeManager.short_type }
,
43 { typeof (ushort), TypeManager.ushort_type }
,
45 { typeof (System.Collections.IEnumerator), TypeManager.ienumerator_type }
,
46 { typeof (System.Collections.IEnumerable), TypeManager.ienumerable_type }
,
47 { typeof (System.IDisposable), TypeManager.idisposable_type }
,
49 { typeof (char), TypeManager.char_type }
,
50 { typeof (string), TypeManager.string_type }
,
51 { typeof (float), TypeManager.float_type }
,
52 { typeof (double), TypeManager.double_type }
,
53 { typeof (decimal), TypeManager.decimal_type }
,
54 { typeof (bool), TypeManager.bool_type }
,
55 { typeof (System.IntPtr), TypeManager.intptr_type }
,
56 { typeof (System.UIntPtr), TypeManager.uintptr_type }
,
58 { typeof (System.MulticastDelegate), TypeManager.multicast_delegate_type }
,
59 { typeof (System.Delegate), TypeManager.delegate_type }
,
60 { typeof (System.Enum), TypeManager.enum_type }
,
61 { typeof (System.Array), TypeManager.array_type }
,
62 { typeof (void), TypeManager.void_type }
,
63 { typeof (System.Type), TypeManager.type_type }
,
64 { typeof (System.Exception), TypeManager.exception_type }
,
65 { typeof (System.RuntimeFieldHandle), TypeManager.runtime_field_handle_type }
,
66 { typeof (System.RuntimeTypeHandle), TypeManager.runtime_handle_type }
70 public static FieldSpec
CreateField (FieldInfo fi
, TypeSpec declaringType
)
73 var fa
= fi
.Attributes
;
74 switch (fa
& FieldAttributes
.FieldAccessMask
) {
75 case FieldAttributes
.Public
:
76 mod
= Modifiers
.PUBLIC
;
78 case FieldAttributes
.Assembly
:
79 mod
= Modifiers
.INTERNAL
;
81 case FieldAttributes
.Family
:
82 mod
= Modifiers
.PROTECTED
;
84 case FieldAttributes
.FamORAssem
:
85 mod
= Modifiers
.PROTECTED
| Modifiers
.INTERNAL
;
88 mod
= Modifiers
.PRIVATE
;
92 // Ignore private fields (even for error reporting) to not require extra dependencies
93 if (mod
== Modifiers
.PRIVATE
)
96 var definition
= new ImportedMemberDefinition (fi
);
98 if ((fa
& FieldAttributes
.Literal
) != 0) {
99 var c
= Constant
.CreateConstantFromValue (ImportType (fi
.FieldType
), fi
.GetValue (fi
), Location
.Null
);
100 return new ConstSpec (declaringType
, definition
, ImportType (fi
.FieldType
), fi
, mod
, c
);
103 if ((fa
& FieldAttributes
.InitOnly
) != 0) {
104 if (fi
.FieldType
== typeof (decimal)) {
105 var dc
= ReadDecimalConstant (fi
);
107 return new ConstSpec (declaringType
, definition
, ImportType (fi
.FieldType
), fi
, mod
, dc
);
110 mod
|= Modifiers
.READONLY
;
112 var reqs
= fi
.GetRequiredCustomModifiers ();
113 if (reqs
.Length
> 0) {
114 foreach (Type t
in reqs
) {
115 if (t
== typeof (System
.Runtime
.CompilerServices
.IsVolatile
)) {
116 mod
|= Modifiers
.VOLATILE
;
123 if ((fa
& FieldAttributes
.Static
) != 0)
124 mod
|= Modifiers
.STATIC
;
126 if (fi
.FieldType
.IsValueType
) {
127 if (fi
.IsDefined (typeof (FixedBufferAttribute
), false)) {
128 var element_field
= CreateField (fi
.FieldType
.GetField (FixedField
.FixedElementName
), declaringType
);
129 return new FixedFieldSpec (declaringType
, definition
, fi
, element_field
, mod
);
133 return new FieldSpec (declaringType
, definition
, ImportType (fi
.FieldType
), fi
, mod
);
136 public static EventSpec
CreateEvent (EventInfo ei
, TypeSpec declaringType
, MethodSpec
add, MethodSpec
remove)
138 add.IsAccessor
= true;
139 remove.IsAccessor
= true;
141 if (add.Modifiers
!= remove.Modifiers
)
142 throw new NotImplementedException ("Different accessor modifiers " + ei
.Name
);
144 var definition
= new ImportedMemberDefinition (ei
);
145 return new EventSpec (declaringType
, definition
, ImportType (ei
.EventHandlerType
), add.Modifiers
, add, remove);
148 static T
[] CreateGenericParameters
<T
> (Type type
, TypeSpec declaringType
) where T
: TypeSpec
150 Type
[] tparams
= type
.GetGenericArguments ();
152 int parent_owned_count
;
154 parent_owned_count
= type
.DeclaringType
.GetGenericArguments ().Length
;
157 // System.Reflection duplicates parent type parameters for each
158 // nested type with slightly modified properties (eg. different owner)
159 // This just makes things more complicated (think of cloned constraints)
160 // therefore we remap any nested type owned by parent using `type_cache'
161 // to the single TypeParameterSpec
163 if (declaringType
!= null && parent_owned_count
> 0) {
165 while (read_count
!= parent_owned_count
) {
166 var tparams_count
= declaringType
.Arity
;
167 if (tparams_count
!= 0) {
168 var parent_tp
= declaringType
.MemberDefinition
.TypeParameters
;
169 read_count
+= tparams_count
;
170 for (int i
= 0; i
< tparams_count
; i
++) {
171 import_cache
.Add (tparams
[parent_owned_count
- read_count
+ i
], parent_tp
[i
]);
175 declaringType
= declaringType
.DeclaringType
;
179 parent_owned_count
= 0;
182 if (tparams
.Length
- parent_owned_count
== 0)
185 return CreateGenericParameters
<T
> (parent_owned_count
, tparams
);
188 static T
[] CreateGenericParameters
<T
> (int first
, Type
[] tparams
) where T
: TypeSpec
190 var tspec
= new T
[tparams
.Length
- first
];
191 for (int pos
= first
; pos
< tparams
.Length
; ++pos
) {
192 var type
= tparams
[pos
];
193 if (type
.HasElementType
) {
194 var element
= type
.GetElementType ();
195 var spec
= CreateType (element
);
198 tspec
[pos
- first
] = (T
) (TypeSpec
) ArrayContainer
.MakeType (spec
, type
.GetArrayRank ());
202 throw new NotImplementedException ("Unknown element type " + type
.ToString ());
205 tspec
[pos
- first
] = (T
) CreateType (type
);
211 public static MethodSpec
CreateMethod (MethodBase mb
, TypeSpec declaringType
)
213 Modifiers mod
= ReadMethodModifiers (mb
, declaringType
);
214 //if (declaringType.IsInterface) {
215 // mod = (mod & ~Modifiers.ABSTRACT) | Modifiers.VIRTUAL;
219 ImportedMethodDefinition definition
;
221 var parameters
= ParametersImported
.Create (declaringType
, mb
);
223 if (mb
.IsGenericMethod
) {
224 if (!mb
.IsGenericMethodDefinition
)
225 throw new NotSupportedException ("assert");
227 var tparams
= CreateGenericParameters
<TypeParameterSpec
>(0, mb
.GetGenericArguments ());
228 definition
= new ImportedGenericMethodDefinition ((MethodInfo
) mb
, parameters
, tparams
);
231 definition
= new ImportedMethodDefinition (mb
, parameters
);
237 if (mb
.MemberType
== MemberTypes
.Constructor
) {
238 kind
= MemberKind
.Constructor
;
239 returnType
= TypeManager
.void_type
;
242 // Detect operators and destructors
244 string name
= mb
.Name
;
245 kind
= MemberKind
.Method
;
246 if (!mb
.DeclaringType
.IsInterface
&& name
.Length
> 6) {
247 if ((mod
& (Modifiers
.STATIC
| Modifiers
.PUBLIC
)) == (Modifiers
.STATIC
| Modifiers
.PUBLIC
)) {
248 if (name
[2] == '_' && name
[1] == 'p' && name
[0] == 'o') {
249 var op_type
= Operator
.GetType (name
);
250 if (op_type
.HasValue
) {
251 kind
= MemberKind
.Operator
;
254 } else if (parameters
.IsEmpty
&& name
== Destructor
.MetadataName
) {
255 kind
= MemberKind
.Destructor
;
259 returnType
= ImportType (((MethodInfo
)mb
).ReturnType
);
262 MethodSpec ms
= new MethodSpec (kind
, declaringType
, definition
, returnType
, mb
, parameters
, mod
);
270 // Returns null when the property is not valid C# property
272 public static PropertySpec
CreateProperty (PropertyInfo pi
, TypeSpec declaringType
, MethodSpec
get, MethodSpec
set)
274 var definition
= new ImportedMemberDefinition (pi
);
277 AParametersCollection param
= null;
278 TypeSpec type
= null;
281 param
= get.Parameters
;
282 type
= get.ReturnType
;
285 bool is_valid_property
= true;
287 if (set.ReturnType
!= TypeManager
.void_type
)
288 is_valid_property
= false;
290 var set_param_count
= set.Parameters
.Count
- 1;
291 if (set_param_count
< 0)
292 is_valid_property
= false;
294 var data
= new IParameterData
[set_param_count
];
295 var types
= new TypeSpec
[set_param_count
];
296 for (int i
= 0; i
< set_param_count
; ++i
) {
297 data
[i
] = set.Parameters
.FixedParameters
[i
];
298 types
[i
] = set.Parameters
.Types
[i
];
301 var set_param
= new ParametersImported (data
, types
);
302 var set_type
= set.Parameters
.Types
[set_param_count
];
309 if (set_param_count
!= get.Parameters
.Count
)
310 is_valid_property
= false;
312 if (get.ReturnType
!= set_type
)
313 is_valid_property
= false;
315 // Possible custom accessor modifiers
316 if ((mod
& ~Modifiers
.AccessibilityMask
) != (set.Modifiers
& ~Modifiers
.AccessibilityMask
)) {
317 var get_acc
= mod
& Modifiers
.AccessibilityMask
;
318 if (get_acc
!= Modifiers
.PUBLIC
) {
319 var set_acc
= set.Modifiers
& Modifiers
.AccessibilityMask
;
320 // If the accessor modifiers are not same, do extra restriction checks
321 if (get_acc
!= set_acc
) {
322 var get_restr
= ModifiersExtensions
.IsRestrictedModifier (get_acc
, set_acc
);
323 var set_restr
= ModifiersExtensions
.IsRestrictedModifier (set_acc
, get_acc
);
324 if (get_restr
&& set_restr
) {
325 is_valid_property
= false; // Neither is more restrictive
329 mod
&= ~Modifiers
.AccessibilityMask
;
338 PropertySpec spec
= null;
339 if (!param
.IsEmpty
) {
340 var index_name
= declaringType
.MemberDefinition
.GetAttributeDefaultMember ();
341 if (index_name
== null) {
342 is_valid_property
= false;
346 is_valid_property
= false;
347 if (get.Name
.IndexOf (index_name
, StringComparison
.Ordinal
) != 4)
348 is_valid_property
= false;
352 is_valid_property
= false;
353 if (set.Name
.IndexOf (index_name
, StringComparison
.Ordinal
) != 4)
354 is_valid_property
= false;
358 if (is_valid_property
)
359 spec
= new IndexerSpec (declaringType
, definition
, type
, param
, pi
, mod
);
363 spec
= new PropertySpec (MemberKind
.Property
, declaringType
, definition
, type
, pi
, mod
);
365 if (!is_valid_property
) {
366 spec
.IsNotRealProperty
= true;
378 public static TypeSpec
CreateType (Type type
)
380 return CreateType (type
, null);
383 public static TypeSpec
CreateType (Type type
, TypeSpec declaringType
)
386 if (import_cache
.TryGetValue (type
, out spec
))
389 if (type
.IsGenericType
&& !type
.IsGenericTypeDefinition
) {
390 var type_def
= type
.GetGenericTypeDefinition ();
391 spec
= CreateType (type_def
, declaringType
);
393 var targs
= CreateGenericParameters
<TypeSpec
> (type
, null);
395 InflatedTypeSpec inflated
;
397 // Inflating nested non-generic type, same in TypeSpec::InflateMember
398 inflated
= new InflatedTypeSpec (spec
, declaringType
, TypeSpec
.EmptyTypes
);
400 // CreateGenericParameters constraint could inflate type
401 if (import_cache
.ContainsKey (type
))
402 return import_cache
[type
];
404 inflated
= spec
.MakeGenericType (targs
);
406 // Use of reading cache to speed up reading only
407 import_cache
.Add (type
, inflated
);
416 var ma
= type
.Attributes
;
417 switch (ma
& TypeAttributes
.VisibilityMask
) {
418 case TypeAttributes
.Public
:
419 case TypeAttributes
.NestedPublic
:
420 mod
= Modifiers
.PUBLIC
;
422 case TypeAttributes
.NestedPrivate
:
423 mod
= Modifiers
.PRIVATE
;
425 case TypeAttributes
.NestedFamily
:
426 mod
= Modifiers
.PROTECTED
;
428 case TypeAttributes
.NestedFamORAssem
:
429 mod
= Modifiers
.PROTECTED
| Modifiers
.INTERNAL
;
432 mod
= Modifiers
.INTERNAL
;
436 if ((ma
& TypeAttributes
.Interface
) != 0) {
437 kind
= MemberKind
.Interface
;
438 } else if (type
.IsGenericParameter
) {
439 kind
= MemberKind
.TypeParameter
;
440 } else if (type
.IsClass
|| type
.IsAbstract
) { // SRE: System.Enum returns false for IsClass
441 if ((ma
& TypeAttributes
.Sealed
) != 0 && type
.IsSubclassOf (typeof (MulticastDelegate
))) {
442 kind
= MemberKind
.Delegate
;
444 kind
= MemberKind
.Class
;
446 if (type
== typeof (object)) {
448 var pa
= PredefinedAttributes
.Get
.Dynamic
.Type
;
449 if (pa
!= null && type
.IsDefined (typeof (DynamicAttribute
), false))
450 return InternalType
.Dynamic
;
454 if ((ma
& TypeAttributes
.Sealed
) != 0) {
455 mod
|= Modifiers
.SEALED
;
456 if ((ma
& TypeAttributes
.Abstract
) != 0)
457 mod
|= Modifiers
.STATIC
;
458 } else if ((ma
& TypeAttributes
.Abstract
) != 0) {
459 mod
|= Modifiers
.ABSTRACT
;
462 } else if (type
.IsEnum
) {
463 kind
= MemberKind
.Enum
;
465 kind
= MemberKind
.Struct
;
466 mod
|= Modifiers
.SEALED
;
469 var definition
= new ImportedTypeDefinition (type
);
470 PredefinedTypeSpec pt
;
472 if (kind
== MemberKind
.Enum
) {
473 const BindingFlags underlying_member
= BindingFlags
.DeclaredOnly
|
474 BindingFlags
.Instance
|
475 BindingFlags
.Public
| BindingFlags
.NonPublic
;
477 var type_members
= type
.GetFields (underlying_member
);
478 foreach (var type_member
in type_members
) {
479 spec
= new EnumSpec (declaringType
, definition
, Import
.CreateType (type_member
.FieldType
), type
, mod
);
484 kind
= MemberKind
.Class
;
486 } else if (kind
== MemberKind
.TypeParameter
) {
487 // Return as type_cache was updated
488 return CreateTypeParameter (type
, declaringType
);
489 } else if (type
.IsGenericTypeDefinition
) {
490 definition
.TypeParameters
= CreateGenericParameters
<TypeParameterSpec
>(type
, declaringType
);
492 // Constraints are not loaded on demand and can reference this type
493 if (import_cache
.TryGetValue (type
, out spec
))
496 } else if (type_2_predefined
.TryGetValue (type
, out pt
)) {
498 pt
.SetDefinition (definition
, type
);
502 spec
= new TypeSpec (kind
, declaringType
, definition
, type
, mod
);
504 import_cache
.Add (type
, spec
);
506 if (kind
== MemberKind
.Interface
)
507 spec
.BaseType
= TypeManager
.object_type
;
508 else if (type
.BaseType
!= null)
509 spec
.BaseType
= CreateType (type
.BaseType
);
511 var ifaces
= type
.GetInterfaces ();
512 if (ifaces
.Length
> 0) {
513 foreach (Type iface
in ifaces
) {
514 spec
.AddInterface (Import
.CreateType (iface
));
521 static TypeParameterSpec
CreateTypeParameter (Type type
, TypeSpec declaringType
)
524 switch (type
.GenericParameterAttributes
& GenericParameterAttributes
.VarianceMask
) {
525 case GenericParameterAttributes
.Covariant
:
526 variance
= Variance
.Covariant
;
528 case GenericParameterAttributes
.Contravariant
:
529 variance
= Variance
.Contravariant
;
532 variance
= Variance
.None
;
536 SpecialConstraint special
= SpecialConstraint
.None
;
537 var import_special
= type
.GenericParameterAttributes
& GenericParameterAttributes
.SpecialConstraintMask
;
539 if ((import_special
& GenericParameterAttributes
.NotNullableValueTypeConstraint
) != 0) {
540 special
|= SpecialConstraint
.Struct
;
541 } else if ((import_special
& GenericParameterAttributes
.DefaultConstructorConstraint
) != 0) {
542 special
= SpecialConstraint
.Constructor
;
545 if ((import_special
& GenericParameterAttributes
.ReferenceTypeConstraint
) != 0) {
546 special
|= SpecialConstraint
.Class
;
549 TypeParameterSpec spec
;
550 var def
= new ImportedTypeParameterDefinition (type
);
551 if (type
.DeclaringMethod
!= null)
552 spec
= new TypeParameterSpec (type
.GenericParameterPosition
, def
, special
, variance
, type
);
554 spec
= new TypeParameterSpec (declaringType
, type
.GenericParameterPosition
, def
, special
, variance
, type
);
556 // Add it now, so any constraint can reference it and get same instance
557 import_cache
.Add (type
, spec
);
559 var constraints
= type
.GetGenericParameterConstraints ();
560 foreach (var ct
in constraints
) {
561 // TODO MemberCache: What to do ??
562 if (ct
.IsGenericParameter
) {
567 if (ct
== typeof (ValueType
)) {
568 spec
.BaseType
= TypeManager
.value_type
;
570 spec
.BaseType
= CreateType (ct
);
576 spec
.AddInterface (CreateType (ct
));
579 if (spec
.BaseType
== null)
580 spec
.BaseType
= TypeManager
.object_type
;
585 public static TypeSpec
ImportType (Type type
)
587 if (type
.HasElementType
) {
588 var element
= type
.GetElementType ();
589 var spec
= ImportType (element
);
592 return ArrayContainer
.MakeType (spec
, type
.GetArrayRank ());
594 return ReferenceContainer
.MakeType (spec
);
596 return PointerContainer
.MakeType (spec
);
598 throw new NotImplementedException ("Unknown element type " + type
.ToString ());
603 dtype
= ImportType (type
.DeclaringType
);
607 return CreateType (type
, dtype
);
611 // Decimal constants cannot be encoded in the constant blob, and thus are marked
612 // as IsInitOnly ('readonly' in C# parlance). We get its value from the
613 // DecimalConstantAttribute metadata.
615 static Constant
ReadDecimalConstant (FieldInfo fi
)
617 object[] attrs
= fi
.GetCustomAttributes (typeof (DecimalConstantAttribute
), false);
618 if (attrs
.Length
!= 1)
621 return new DecimalConstant (((DecimalConstantAttribute
) attrs
[0]).Value
, Location
.Null
);
624 static Modifiers
ReadMethodModifiers (MethodBase mb
, TypeSpec declaringType
)
627 var ma
= mb
.Attributes
;
628 switch (ma
& MethodAttributes
.MemberAccessMask
) {
629 case MethodAttributes
.Public
:
630 mod
= Modifiers
.PUBLIC
;
632 case MethodAttributes
.Assembly
:
633 mod
= Modifiers
.INTERNAL
;
635 case MethodAttributes
.Family
:
636 mod
= Modifiers
.PROTECTED
;
638 case MethodAttributes
.FamORAssem
:
639 mod
= Modifiers
.PROTECTED
| Modifiers
.INTERNAL
;
642 mod
= Modifiers
.PRIVATE
;
646 if ((ma
& MethodAttributes
.Static
) != 0) {
647 mod
|= Modifiers
.STATIC
;
648 } else if ((ma
& MethodAttributes
.Final
) != 0) {
649 mod
|= Modifiers
.SEALED
;
650 } else if ((ma
& MethodAttributes
.Abstract
) != 0 && declaringType
.IsClass
) {
651 mod
|= Modifiers
.ABSTRACT
;
654 // It can be sealed and override
655 if ((ma
& MethodAttributes
.Virtual
) != 0) {
656 if ((ma
& MethodAttributes
.NewSlot
) != 0 || !declaringType
.IsClass
|| mod
== Modifiers
.PRIVATE
) {
657 mod
|= Modifiers
.VIRTUAL
;
659 // Cannot set to OVERRIDE without full hierarchy checks
660 // this flag indicates that the method could be override
661 // but further validation is needed
662 mod
|= Modifiers
.OVERRIDE_UNCHECKED
;
670 class ImportedMemberDefinition
: IMemberDefinition
672 protected class AttributesBag
674 public static readonly AttributesBag Default
= new AttributesBag ();
676 public AttributeUsageAttribute AttributeUsage
;
677 public ObsoleteAttribute Obsolete
;
678 public string[] Conditionals
;
679 public string DefaultIndexerName
;
680 public bool IsNotCLSCompliant
;
682 public static AttributesBag
Read (MemberInfo mi
)
684 AttributesBag bag
= null;
685 List
<string> conditionals
= null;
687 var attrs
= CustomAttributeData
.GetCustomAttributes (mi
);
688 foreach (var a
in attrs
) {
689 var type
= a
.Constructor
.DeclaringType
;
690 if (type
== typeof (ObsoleteAttribute
)) {
692 bag
= new AttributesBag ();
694 var args
= a
.ConstructorArguments
;
696 if (args
.Count
== 1) {
697 bag
.Obsolete
= new ObsoleteAttribute ((string) args
[0].Value
);
698 } else if (args
.Count
== 2) {
699 bag
.Obsolete
= new ObsoleteAttribute ((string) args
[0].Value
, (bool) args
[1].Value
);
701 bag
.Obsolete
= new ObsoleteAttribute ();
707 if (type
== typeof (ConditionalAttribute
)) {
709 bag
= new AttributesBag ();
711 if (conditionals
== null)
712 conditionals
= new List
<string> (2);
714 conditionals
.Add ((string) a
.ConstructorArguments
[0].Value
);
718 if (type
== typeof (CLSCompliantAttribute
)) {
720 bag
= new AttributesBag ();
722 bag
.IsNotCLSCompliant
= !(bool) a
.ConstructorArguments
[0].Value
;
726 // Type only attributes
727 if (type
== typeof (DefaultMemberAttribute
)) {
729 bag
= new AttributesBag ();
731 bag
.DefaultIndexerName
= (string) a
.ConstructorArguments
[0].Value
;
735 if (type
== typeof (AttributeUsageAttribute
)) {
737 bag
= new AttributesBag ();
739 bag
.AttributeUsage
= new AttributeUsageAttribute ((AttributeTargets
) a
.ConstructorArguments
[0].Value
);
740 foreach (var named
in a
.NamedArguments
) {
741 if (named
.MemberInfo
.Name
== "AllowMultiple")
742 bag
.AttributeUsage
.AllowMultiple
= (bool) named
.TypedValue
.Value
;
743 else if (named
.MemberInfo
.Name
== "Inherited")
744 bag
.AttributeUsage
.Inherited
= (bool) named
.TypedValue
.Value
;
753 if (conditionals
!= null)
754 bag
.Conditionals
= conditionals
.ToArray ();
760 protected readonly MemberInfo provider
;
761 protected AttributesBag cattrs
;
763 public ImportedMemberDefinition (MemberInfo provider
)
765 this.provider
= provider
;
770 public Assembly Assembly
{
772 return provider
.Module
.Assembly
;
776 public bool IsImported
{
782 public virtual string Name
{
784 return provider
.Name
;
790 public string[] ConditionalConditions ()
795 return cattrs
.Conditionals
;
798 public ObsoleteAttribute
GetAttributeObsolete ()
803 return cattrs
.Obsolete
;
806 public bool IsNotCLSCompliant ()
811 return cattrs
.IsNotCLSCompliant
;
814 protected void ReadAttributes ()
816 cattrs
= AttributesBag
.Read (provider
);
819 public void SetIsAssigned ()
821 // Unused for imported members
824 public void SetIsUsed ()
826 // Unused for imported members
830 class ImportedMethodDefinition
: ImportedMemberDefinition
, IParametersMember
832 readonly AParametersCollection parameters
;
834 public ImportedMethodDefinition (MethodBase provider
, AParametersCollection parameters
)
837 this.parameters
= parameters
;
842 public AParametersCollection Parameters
{
848 public TypeSpec MemberType
{
850 throw new NotImplementedException ();
857 class ImportedGenericMethodDefinition
: ImportedMethodDefinition
, IGenericMethodDefinition
859 TypeParameterSpec
[] tparams
;
861 public ImportedGenericMethodDefinition (MethodInfo provider
, AParametersCollection parameters
, TypeParameterSpec
[] tparams
)
862 : base (provider
, parameters
)
864 this.tparams
= tparams
;
869 public TypeParameterSpec
[] TypeParameters
{
875 public int TypeParametersCount
{
877 return tparams
.Length
;
884 class ImportedTypeDefinition
: ImportedMemberDefinition
, ITypeDefinition
886 TypeParameterSpec
[] tparams
;
889 public ImportedTypeDefinition (Type type
)
896 public override string Name
{
901 name
= name
.Substring (0, name
.IndexOf ('`'));
908 public string Namespace
{
910 return ((Type
) provider
).Namespace
;
914 public int TypeParametersCount
{
916 return tparams
== null ? 0 : tparams
.Length
;
920 public TypeParameterSpec
[] TypeParameters
{
931 public TypeSpec
GetAttributeCoClass ()
933 // TODO: Use ReadAttributes
934 var attr
= provider
.GetCustomAttributes (typeof (CoClassAttribute
), false);
938 return Import
.CreateType (((CoClassAttribute
) attr
[0]).CoClass
);
941 public string GetAttributeDefaultMember ()
946 return cattrs
.DefaultIndexerName
;
949 public AttributeUsageAttribute
GetAttributeUsage (PredefinedAttribute pa
)
954 return cattrs
.AttributeUsage
;
957 public MemberCache
LoadMembers (TypeSpec declaringType
)
959 var loading_type
= (Type
) provider
;
960 const BindingFlags all_members
= BindingFlags
.DeclaredOnly
|
961 BindingFlags
.Static
| BindingFlags
.Instance
|
962 BindingFlags
.Public
| BindingFlags
.NonPublic
;
964 const MethodAttributes explicit_impl
= MethodAttributes
.NewSlot
|
965 MethodAttributes
.Virtual
| MethodAttributes
.HideBySig
|
966 MethodAttributes
.Final
;
968 Dictionary
<MethodBase
, MethodSpec
> possible_accessors
= null;
971 List
<string> fields_to_ignore
= null;
974 // This requires methods to be returned first which seems to work for both Mono and .NET
976 var all
= loading_type
.GetMembers (all_members
);
978 var cache
= new MemberCache (all
.Length
);
979 foreach (var member
in all
) {
980 switch (member
.MemberType
) {
981 case MemberTypes
.Constructor
:
982 case MemberTypes
.Method
:
983 MethodBase mb
= (MethodBase
) member
;
985 // Ignore explicitly implemented members
986 if ((mb
.Attributes
& explicit_impl
) == explicit_impl
&& (mb
.Attributes
& MethodAttributes
.MemberAccessMask
) == MethodAttributes
.Private
)
989 // Ignore compiler generated methods
990 if (mb
.IsPrivate
&& mb
.IsDefined (typeof (CompilerGeneratedAttribute
), false))
993 imported
= Import
.CreateMethod (mb
, declaringType
);
994 if (imported
.Kind
== MemberKind
.Method
) {
995 if (possible_accessors
== null)
996 possible_accessors
= new Dictionary
<MethodBase
, MethodSpec
> (ReferenceEquality
<MethodBase
>.Default
);
998 // There are no metadata rules for accessors, we have to any method as possible candidate
999 possible_accessors
.Add (mb
, (MethodSpec
) imported
);
1003 case MemberTypes
.Property
:
1004 if (possible_accessors
== null)
1007 var p
= (PropertyInfo
) member
;
1009 // Links possible accessors with property
1011 MethodSpec
get, set;
1012 m
= p
.GetGetMethod (true);
1013 if (m
== null || !possible_accessors
.TryGetValue (m
, out get))
1016 m
= p
.GetSetMethod (true);
1017 if (m
== null || !possible_accessors
.TryGetValue (m
, out set))
1020 // No accessors registered (e.g. explicit implementation)
1021 if (get == null && set == null)
1024 imported
= Import
.CreateProperty (p
, declaringType
, get, set);
1025 if (imported
== null)
1029 case MemberTypes
.Event
:
1030 if (possible_accessors
== null)
1033 var e
= (EventInfo
) member
;
1035 // Links accessors with event
1037 MethodSpec
add, remove;
1038 m
= e
.GetAddMethod (true);
1039 if (m
== null || !possible_accessors
.TryGetValue (m
, out add))
1042 m
= e
.GetRemoveMethod (true);
1043 if (m
== null || !possible_accessors
.TryGetValue (m
, out remove))
1046 // Both accessors are required
1047 if (add == null || remove == null)
1050 if (fields_to_ignore
== null)
1051 fields_to_ignore
= new List
<string> ();
1053 fields_to_ignore
.Add (e
.Name
);
1055 imported
= Import
.CreateEvent (e
, declaringType
, add, remove);
1057 case MemberTypes
.Field
:
1058 var fi
= (FieldInfo
) member
;
1060 // Ignore compiler generated fields
1061 if (fi
.IsPrivate
&& fi
.IsDefined (typeof (CompilerGeneratedAttribute
), false))
1064 if (fields_to_ignore
!= null && fields_to_ignore
.Contains (fi
.Name
))
1067 imported
= Import
.CreateField (fi
, declaringType
);
1068 if (imported
== null)
1072 case MemberTypes
.NestedType
:
1073 Type t
= (Type
) member
;
1075 // Ignore compiler generated types, mostly lambda containers
1076 if (t
.IsNotPublic
&& t
.IsDefined (typeof (CompilerGeneratedAttribute
), false))
1079 imported
= Import
.CreateType (t
, declaringType
);
1082 throw new NotImplementedException (member
.ToString ());
1085 cache
.AddMember (imported
);
1088 if (declaringType
.IsInterface
&& declaringType
.Interfaces
!= null) {
1089 foreach (var iface
in declaringType
.Interfaces
) {
1090 cache
.AddInterface (iface
);
1098 class ImportedTypeParameterDefinition
: ImportedMemberDefinition
, ITypeDefinition
1100 public ImportedTypeParameterDefinition (Type type
)
1107 public string Namespace
{
1113 public int TypeParametersCount
{
1119 public TypeParameterSpec
[] TypeParameters
{
1127 public TypeSpec
GetAttributeCoClass ()
1132 public string GetAttributeDefaultMember ()
1134 throw new NotSupportedException ();
1137 public AttributeUsageAttribute
GetAttributeUsage (PredefinedAttribute pa
)
1139 throw new NotSupportedException ();
1142 public MemberCache
LoadMembers (TypeSpec declaringType
)
1144 throw new NotImplementedException ();