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 var definition = new ImportedMemberDefinition (fi);
94 if ((fa & FieldAttributes.Literal) != 0) {
95 var c = Constant.CreateConstantFromValue (ImportType (fi.FieldType), fi.GetValue (fi), Location.Null);
96 return new ConstSpec (declaringType, definition, ImportType (fi.FieldType), fi, mod, c);
99 if ((fa & FieldAttributes.InitOnly) != 0) {
100 if (fi.FieldType == typeof (decimal)) {
101 var dc = ReadDecimalConstant (fi);
103 return new ConstSpec (declaringType, definition, ImportType (fi.FieldType), fi, mod, dc);
106 mod |= Modifiers.READONLY;
109 if ((fa & FieldAttributes.Static) != 0)
110 mod |= Modifiers.STATIC;
112 if (fi.FieldType.IsValueType) {
113 if (fi.IsDefined (typeof (FixedBufferAttribute), false)) {
114 var element_field = CreateField (fi.FieldType.GetField (FixedField.FixedElementName), declaringType);
115 return new FixedFieldSpec (declaringType, definition, fi, element_field, mod);
119 // TODO: import volatile
121 return new FieldSpec (declaringType, definition, ImportType (fi.FieldType), fi, mod);
124 public static EventSpec CreateEvent (EventInfo ei, TypeSpec declaringType, MethodSpec add, MethodSpec remove)
126 add.IsAccessor = true;
127 remove.IsAccessor = true;
129 if (add.Modifiers != remove.Modifiers)
130 throw new NotImplementedException ("Different accessor modifiers " + ei.Name);
132 var definition = new ImportedMemberDefinition (ei);
133 return new EventSpec (declaringType, definition, ImportType (ei.EventHandlerType), add.Modifiers, add, remove);
136 static T[] CreateGenericParameters<T> (Type type, TypeSpec declaringType) where T : TypeSpec
138 Type[] tparams = type.GetGenericArguments ();
140 int parent_owned_count;
142 parent_owned_count = type.DeclaringType.GetGenericArguments ().Length;
145 // System.Reflection duplicates parent type parameters for each
146 // nested type with slightly modified properties (eg. different owner)
147 // This just makes things more complicated (think of cloned constraints)
148 // therefore we remap any nested type owned by parent using `type_cache'
149 // to the single TypeParameterSpec
151 if (declaringType != null && parent_owned_count > 0) {
153 while (read_count != parent_owned_count) {
154 var tparams_count = declaringType.Arity;
155 if (tparams_count != 0) {
156 var parent_tp = declaringType.MemberDefinition.TypeParameters;
157 read_count += tparams_count;
158 for (int i = 0; i < tparams_count; i++) {
159 import_cache.Add (tparams[parent_owned_count - read_count + i], parent_tp[i]);
163 declaringType = declaringType.DeclaringType;
167 parent_owned_count = 0;
170 if (tparams.Length - parent_owned_count == 0)
173 return CreateGenericParameters<T> (parent_owned_count, tparams);
176 static T[] CreateGenericParameters<T> (int first, Type[] tparams) where T : TypeSpec
178 var tspec = new T [tparams.Length - first];
179 for (int pos = first; pos < tparams.Length; ++pos) {
180 tspec [pos - first] = (T) CreateType (tparams [pos]);
186 public static MethodSpec CreateMethod (MethodBase mb, TypeSpec declaringType)
188 Modifiers mod = ReadMethodModifiers (mb, declaringType);
189 //if (declaringType.IsInterface) {
190 // mod = (mod & ~Modifiers.ABSTRACT) | Modifiers.VIRTUAL;
194 ImportedMethodDefinition definition;
196 var parameters = ParametersImported.Create (declaringType, mb);
198 if (mb.IsGenericMethod) {
199 if (!mb.IsGenericMethodDefinition)
200 throw new NotSupportedException ("assert");
202 var tparams = CreateGenericParameters<TypeParameterSpec>(0, mb.GetGenericArguments ());
203 definition = new ImportedGenericMethodDefinition ((MethodInfo) mb, parameters, tparams);
206 definition = new ImportedMethodDefinition (mb, parameters);
212 if (mb.MemberType == MemberTypes.Constructor) {
213 kind = MemberKind.Constructor;
214 returnType = TypeManager.void_type;
217 // Detect operators and destructors
219 string name = mb.Name;
220 kind = MemberKind.Method;
221 if (!mb.DeclaringType.IsInterface && name.Length > 6) {
222 if ((mod & (Modifiers.STATIC | Modifiers.PUBLIC)) == (Modifiers.STATIC | Modifiers.PUBLIC)) {
223 if (name[2] == '_' && name[1] == 'p' && name[0] == 'o') {
224 var op_type = Operator.GetType (name);
225 if (op_type.HasValue) {
226 kind = MemberKind.Operator;
229 } else if (parameters.IsEmpty && name == Destructor.MetadataName) {
230 kind = MemberKind.Destructor;
234 returnType = ImportType (((MethodInfo)mb).ReturnType);
237 MethodSpec ms = new MethodSpec (kind, declaringType, definition, returnType, mb, parameters, mod);
245 // Returns null when the property is not valid C# property
247 public static PropertySpec CreateProperty (PropertyInfo pi, TypeSpec declaringType, MethodSpec get, MethodSpec set)
249 var definition = new ImportedMemberDefinition (pi);
252 AParametersCollection param = null;
253 TypeSpec type = null;
256 param = get.Parameters;
257 type = get.ReturnType;
260 bool is_valid_property = true;
262 if (set.ReturnType != TypeManager.void_type)
263 is_valid_property = false;
265 var set_param_count = set.Parameters.Count - 1;
266 if (set_param_count < 0)
267 is_valid_property = false;
269 var data = new IParameterData [set_param_count];
270 var types = new TypeSpec[set_param_count];
271 for (int i = 0; i < set_param_count; ++i ) {
272 data[i] = set.Parameters.FixedParameters[i];
273 types[i] = set.Parameters.Types[i];
276 var set_param = new ParametersImported (data, types);
277 var set_type = set.Parameters.Types[set_param_count];
284 if (set_param_count != get.Parameters.Count)
285 is_valid_property = false;
287 if (get.ReturnType != set_type)
288 is_valid_property = false;
290 // Possible custom accessor modifiers
291 if ((mod & ~Modifiers.AccessibilityMask) != (set.Modifiers & ~Modifiers.AccessibilityMask)) {
292 var get_acc = mod & Modifiers.AccessibilityMask;
293 if (get_acc != Modifiers.PUBLIC) {
294 var set_acc = set.Modifiers & Modifiers.AccessibilityMask;
295 // If the accessor modifiers are not same, do extra restriction checks
296 if (get_acc != set_acc) {
297 var get_restr = ModifiersExtensions.IsRestrictedModifier (get_acc, set_acc);
298 var set_restr = ModifiersExtensions.IsRestrictedModifier (set_acc, get_acc);
299 if (get_restr && set_restr) {
300 is_valid_property = false; // Neither is more restrictive
304 mod &= ~Modifiers.AccessibilityMask;
313 PropertySpec spec = null;
314 if (!param.IsEmpty) {
315 var index_name = declaringType.MemberDefinition.GetAttributeDefaultMember ();
316 if (index_name == null) {
317 is_valid_property = false;
321 is_valid_property = false;
322 if (get.Name.IndexOf (index_name, StringComparison.Ordinal) != 4)
323 is_valid_property = false;
327 is_valid_property = false;
328 if (set.Name.IndexOf (index_name, StringComparison.Ordinal) != 4)
329 is_valid_property = false;
333 if (is_valid_property)
334 spec = new IndexerSpec (declaringType, definition, type, param, pi, mod);
338 spec = new PropertySpec (MemberKind.Property, declaringType, definition, type, pi, mod);
340 if (!is_valid_property) {
341 spec.IsNotRealProperty = true;
353 public static TypeSpec CreateType (Type type)
355 return CreateType (type, null);
358 public static TypeSpec CreateType (Type type, TypeSpec declaringType)
361 if (import_cache.TryGetValue (type, out spec))
364 if (type.IsGenericType && !type.IsGenericTypeDefinition) {
365 var type_def = type.GetGenericTypeDefinition ();
366 spec = CreateType (type_def, declaringType);
368 var targs = CreateGenericParameters<TypeSpec> (type, null);
370 InflatedTypeSpec inflated;
372 // Inflating nested non-generic type, same in TypeSpec::InflateMember
373 inflated = new InflatedTypeSpec (spec, declaringType, TypeSpec.EmptyTypes);
375 // CreateGenericParameters constraint could inflate type
376 if (import_cache.ContainsKey (type))
377 return import_cache[type];
379 inflated = spec.MakeGenericType (targs);
381 // Use of reading cache to speed up reading only
382 import_cache.Add (type, inflated);
391 var ma = type.Attributes;
392 switch (ma & TypeAttributes.VisibilityMask) {
393 case TypeAttributes.Public:
394 case TypeAttributes.NestedPublic:
395 mod = Modifiers.PUBLIC;
397 case TypeAttributes.NestedPrivate:
398 mod = Modifiers.PRIVATE;
400 case TypeAttributes.NestedFamily:
401 mod = Modifiers.PROTECTED;
403 case TypeAttributes.NestedFamORAssem:
404 mod = Modifiers.PROTECTED | Modifiers.INTERNAL;
407 mod = Modifiers.INTERNAL;
411 if ((ma & TypeAttributes.Interface) != 0) {
412 kind = MemberKind.Interface;
413 } else if (type.IsGenericParameter) {
414 kind = MemberKind.TypeParameter;
415 } else if (type.IsClass || type.IsAbstract) { // SRE: System.Enum returns false for IsClass
416 if ((ma & TypeAttributes.Sealed) != 0 && type.IsSubclassOf (typeof (MulticastDelegate))) {
417 kind = MemberKind.Delegate;
419 kind = MemberKind.Class;
421 if (type == typeof (object)) {
423 var pa = PredefinedAttributes.Get.Dynamic.Type;
424 if (pa != null && type.IsDefined (typeof (DynamicAttribute), false))
425 return InternalType.Dynamic;
429 if ((ma & TypeAttributes.Sealed) != 0) {
430 mod |= Modifiers.SEALED;
431 if ((ma & TypeAttributes.Abstract) != 0)
432 mod |= Modifiers.STATIC;
433 } else if ((ma & TypeAttributes.Abstract) != 0) {
434 mod |= Modifiers.ABSTRACT;
437 } else if (type.IsEnum) {
438 kind = MemberKind.Enum;
440 kind = MemberKind.Struct;
441 mod |= Modifiers.SEALED;
444 var definition = new ImportedTypeDefinition (type);
445 PredefinedTypeSpec pt;
447 if (kind == MemberKind.Enum) {
448 const BindingFlags any_member = BindingFlags.DeclaredOnly |
449 BindingFlags.Static | BindingFlags.Instance |
450 BindingFlags.Public | BindingFlags.NonPublic;
452 var u_type = type.GetField (Enum.UnderlyingValueField, any_member);
453 if (u_type != null) {
454 spec = new EnumSpec (declaringType, definition, Import.CreateType (u_type.FieldType), type, mod);
456 } else if (kind == MemberKind.TypeParameter) {
457 // Return as type_cache was updated
458 return CreateTypeParameter (type, declaringType);
459 } else if (type.IsGenericTypeDefinition) {
460 definition.TypeParameters = CreateGenericParameters<TypeParameterSpec>(type, declaringType);
462 // Constraints are not loaded on demand and can reference this type
463 if (import_cache.TryGetValue (type, out spec))
466 } else if (type_2_predefined.TryGetValue (type, out pt)) {
468 pt.SetDefinition (definition, type);
472 spec = new TypeSpec (kind, declaringType, definition, type, mod);
474 import_cache.Add (type, spec);
476 if (kind == MemberKind.Interface)
477 spec.BaseType = TypeManager.object_type;
478 else if (type.BaseType != null)
479 spec.BaseType = CreateType (type.BaseType);
481 var ifaces = type.GetInterfaces ();
482 if (ifaces.Length > 0) {
483 foreach (Type iface in ifaces) {
484 spec.AddInterface (Import.CreateType (iface));
491 static TypeParameterSpec CreateTypeParameter (Type type, TypeSpec declaringType)
494 switch (type.GenericParameterAttributes & GenericParameterAttributes.VarianceMask) {
495 case GenericParameterAttributes.Covariant:
496 variance = Variance.Covariant;
498 case GenericParameterAttributes.Contravariant:
499 variance = Variance.Contravariant;
502 variance = Variance.None;
506 SpecialConstraint special = SpecialConstraint.None;
507 var import_special = type.GenericParameterAttributes & GenericParameterAttributes.SpecialConstraintMask;
509 if ((import_special & GenericParameterAttributes.NotNullableValueTypeConstraint) != 0) {
510 special |= SpecialConstraint.Struct;
511 } else if ((import_special & GenericParameterAttributes.DefaultConstructorConstraint) != 0) {
512 special = SpecialConstraint.Constructor;
515 if ((import_special & GenericParameterAttributes.ReferenceTypeConstraint) != 0) {
516 special |= SpecialConstraint.Class;
519 TypeParameterSpec spec;
520 var def = new ImportedTypeParameterDefinition (type);
521 if (type.DeclaringMethod != null)
522 spec = new TypeParameterSpec (type.GenericParameterPosition, def, special, variance, type);
524 spec = new TypeParameterSpec (declaringType, type.GenericParameterPosition, def, special, variance, type);
526 // Add it now, so any constraint can reference it and get same instance
527 import_cache.Add (type, spec);
529 var constraints = type.GetGenericParameterConstraints ();
530 foreach (var ct in constraints) {
531 // TODO MemberCache: What to do ??
532 if (ct.IsGenericParameter) {
537 if (ct == typeof (ValueType)) {
538 spec.BaseType = TypeManager.value_type;
540 spec.BaseType = CreateType (ct);
546 spec.AddInterface (CreateType (ct));
549 if (spec.BaseType == null)
550 spec.BaseType = TypeManager.object_type;
555 public static TypeSpec ImportType (Type type)
557 if (type.HasElementType) {
558 var element = type.GetElementType ();
559 var spec = ImportType (element);
562 return ArrayContainer.MakeType (spec, type.GetArrayRank ());
564 return ReferenceContainer.MakeType (spec);
566 return PointerContainer.MakeType (spec);
568 throw new NotImplementedException ("Unknown element type " + type.ToString ());
573 dtype = ImportType (type.DeclaringType);
577 return CreateType (type, dtype);
581 // Decimal constants cannot be encoded in the constant blob, and thus are marked
582 // as IsInitOnly ('readonly' in C# parlance). We get its value from the
583 // DecimalConstantAttribute metadata.
585 static Constant ReadDecimalConstant (FieldInfo fi)
587 object[] attrs = fi.GetCustomAttributes (typeof (DecimalConstantAttribute), false);
588 if (attrs.Length != 1)
591 return new DecimalConstant (((DecimalConstantAttribute) attrs [0]).Value, Location.Null);
594 static Modifiers ReadMethodModifiers (MethodBase mb, TypeSpec declaringType)
597 var ma = mb.Attributes;
598 switch (ma & MethodAttributes.MemberAccessMask) {
599 case MethodAttributes.Public:
600 mod = Modifiers.PUBLIC;
602 case MethodAttributes.Assembly:
603 mod = Modifiers.INTERNAL;
605 case MethodAttributes.Family:
606 mod = Modifiers.PROTECTED;
608 case MethodAttributes.FamORAssem:
609 mod = Modifiers.PROTECTED | Modifiers.INTERNAL;
612 mod = Modifiers.PRIVATE;
616 if ((ma & MethodAttributes.Static) != 0) {
617 mod |= Modifiers.STATIC;
618 } else if ((ma & MethodAttributes.Final) != 0) {
619 mod |= Modifiers.SEALED;
620 } else if ((ma & MethodAttributes.Abstract) != 0 && declaringType.IsClass) {
621 mod |= Modifiers.ABSTRACT;
624 // It can be sealed and override
625 if ((ma & MethodAttributes.Virtual) != 0) {
626 if ((ma & MethodAttributes.NewSlot) != 0 || !declaringType.IsClass || mod == Modifiers.PRIVATE) {
627 mod |= Modifiers.VIRTUAL;
629 // Cannot set to OVERRIDE without full hierarchy checks
630 // this flag indicates that the method could be override
631 // but further validation is needed
632 mod |= Modifiers.OVERRIDE_UNCHECKED;
640 class ImportedMemberDefinition : IMemberDefinition
642 protected class AttributesBag
644 public static readonly AttributesBag Default = new AttributesBag ();
646 public AttributeUsageAttribute AttributeUsage;
647 public ObsoleteAttribute Obsolete;
648 public string[] Conditionals;
649 public string DefaultIndexerName;
650 public bool IsNotCLSCompliant;
652 public static AttributesBag Read (MemberInfo mi)
654 AttributesBag bag = null;
655 List<string> conditionals = null;
657 var attrs = CustomAttributeData.GetCustomAttributes (mi);
658 foreach (var a in attrs) {
659 var type = a.Constructor.DeclaringType;
660 if (type == typeof (ObsoleteAttribute)) {
662 bag = new AttributesBag ();
664 var args = a.ConstructorArguments;
666 if (args.Count == 1) {
667 bag.Obsolete = new ObsoleteAttribute ((string) args[0].Value);
668 } else if (args.Count == 2) {
669 bag.Obsolete = new ObsoleteAttribute ((string) args[0].Value, (bool) args[1].Value);
671 bag.Obsolete = new ObsoleteAttribute ();
677 if (type == typeof (ConditionalAttribute)) {
679 bag = new AttributesBag ();
681 if (conditionals == null)
682 conditionals = new List<string> (2);
684 conditionals.Add ((string) a.ConstructorArguments[0].Value);
688 if (type == typeof (CLSCompliantAttribute)) {
690 bag = new AttributesBag ();
692 bag.IsNotCLSCompliant = !(bool) a.ConstructorArguments[0].Value;
696 // Type only attributes
697 if (type == typeof (DefaultMemberAttribute)) {
699 bag = new AttributesBag ();
701 bag.DefaultIndexerName = (string) a.ConstructorArguments[0].Value;
705 if (type == typeof (AttributeUsageAttribute)) {
707 bag = new AttributesBag ();
709 bag.AttributeUsage = new AttributeUsageAttribute ((AttributeTargets) a.ConstructorArguments[0].Value);
710 foreach (var named in a.NamedArguments) {
711 if (named.MemberInfo.Name == "AllowMultiple")
712 bag.AttributeUsage.AllowMultiple = (bool) named.TypedValue.Value;
713 else if (named.MemberInfo.Name == "Inherited")
714 bag.AttributeUsage.Inherited = (bool) named.TypedValue.Value;
723 if (conditionals != null)
724 bag.Conditionals = conditionals.ToArray ();
730 protected readonly MemberInfo provider;
731 protected AttributesBag cattrs;
733 public ImportedMemberDefinition (MemberInfo provider)
735 this.provider = provider;
740 public Assembly Assembly {
742 return provider.Module.Assembly;
746 public bool IsImported {
752 public virtual string Name {
754 return provider.Name;
760 public string[] ConditionalConditions ()
765 return cattrs.Conditionals;
768 public ObsoleteAttribute GetAttributeObsolete ()
773 return cattrs.Obsolete;
776 public bool IsNotCLSCompliant ()
781 return cattrs.IsNotCLSCompliant;
784 protected void ReadAttributes ()
786 cattrs = AttributesBag.Read (provider);
789 public void SetIsAssigned ()
791 // Unused for imported members
794 public void SetIsUsed ()
796 // Unused for imported members
800 class ImportedMethodDefinition : ImportedMemberDefinition, IParametersMember
802 readonly AParametersCollection parameters;
804 public ImportedMethodDefinition (MethodBase provider, AParametersCollection parameters)
807 this.parameters = parameters;
812 public AParametersCollection Parameters {
818 public TypeSpec MemberType {
820 throw new NotImplementedException ();
827 class ImportedGenericMethodDefinition : ImportedMethodDefinition, IGenericMethodDefinition
829 TypeParameterSpec[] tparams;
831 public ImportedGenericMethodDefinition (MethodInfo provider, AParametersCollection parameters, TypeParameterSpec[] tparams)
832 : base (provider, parameters)
834 this.tparams = tparams;
839 public TypeParameterSpec[] TypeParameters {
845 public int TypeParametersCount {
847 return tparams.Length;
854 class ImportedTypeDefinition : ImportedMemberDefinition, ITypeDefinition
856 TypeParameterSpec[] tparams;
859 public ImportedTypeDefinition (Type type)
866 public override string Name {
871 name = name.Substring (0, name.IndexOf ('`'));
878 public string Namespace {
880 return ((Type) provider).Namespace;
884 public int TypeParametersCount {
886 return tparams == null ? 0 : tparams.Length;
890 public TypeParameterSpec[] TypeParameters {
901 public TypeSpec GetAttributeCoClass ()
903 // TODO: Use ReadAttributes
904 var attr = provider.GetCustomAttributes (typeof (CoClassAttribute), false);
908 return Import.CreateType (((CoClassAttribute) attr[0]).CoClass);
911 public string GetAttributeDefaultMember ()
916 return cattrs.DefaultIndexerName;
919 public AttributeUsageAttribute GetAttributeUsage (PredefinedAttribute pa)
924 return cattrs.AttributeUsage;
927 public MemberCache LoadMembers (TypeSpec declaringType)
929 var loading_type = (Type) provider;
930 const BindingFlags all_members = BindingFlags.DeclaredOnly |
931 BindingFlags.Static | BindingFlags.Instance |
932 BindingFlags.Public | BindingFlags.NonPublic;
934 const MethodAttributes explicit_impl = MethodAttributes.NewSlot |
935 MethodAttributes.Virtual | MethodAttributes.HideBySig |
936 MethodAttributes.Final | MethodAttributes.Private;
938 Dictionary<MethodBase, MethodSpec> possible_accessors = null;
941 List<string> fields_to_ignore = null;
944 // This requires methods to be returned first which seems to work for both Mono and .NET
946 var all = loading_type.GetMembers (all_members);
948 var cache = new MemberCache (all.Length);
949 foreach (var member in all) {
950 switch (member.MemberType) {
951 case MemberTypes.Constructor:
952 case MemberTypes.Method:
953 MethodBase mb = (MethodBase) member;
955 // Ignore explicitly implemented members
956 if ((mb.Attributes & explicit_impl) == explicit_impl)
959 // Ignore compiler generated methods
960 if (mb.IsPrivate && mb.IsDefined (typeof (CompilerGeneratedAttribute), false))
963 imported = Import.CreateMethod (mb, declaringType);
964 var name = imported.Name;
965 if (imported.Kind == MemberKind.Method && name.Length > 4) {
966 if ((name[3] == '_' && (name.StartsWith ("get", StringComparison.Ordinal) ||
967 name.StartsWith ("set", StringComparison.Ordinal) ||
968 name.StartsWith ("add", StringComparison.Ordinal))) ||
969 name.Length > 7 && name[6] == '_' && name.StartsWith ("remove", StringComparison.Ordinal)) {
971 if (possible_accessors == null)
972 possible_accessors = new Dictionary<MethodBase, MethodSpec> ();
974 possible_accessors.Add (mb, (MethodSpec) imported);
979 case MemberTypes.Property:
980 if (possible_accessors == null)
983 var p = (PropertyInfo) member;
985 // Links possible accessors with property
988 m = p.GetGetMethod (true);
989 if (m == null || !possible_accessors.TryGetValue (m, out get))
992 m = p.GetSetMethod (true);
993 if (m == null || !possible_accessors.TryGetValue (m, out set))
996 // No accessors registered (e.g. explicit implementation)
997 if (get == null && set == null)
1000 imported = Import.CreateProperty (p, declaringType, get, set);
1001 if (imported == null)
1005 case MemberTypes.Event:
1006 if (possible_accessors == null)
1009 var e = (EventInfo) member;
1011 // Links accessors with event
1013 MethodSpec add, remove;
1014 m = e.GetAddMethod (true);
1015 if (m == null || !possible_accessors.TryGetValue (m, out add))
1018 m = e.GetRemoveMethod (true);
1019 if (m == null || !possible_accessors.TryGetValue (m, out remove))
1022 // Both accessors are required
1023 if (add == null || remove == null)
1026 if (fields_to_ignore == null)
1027 fields_to_ignore = new List<string> ();
1029 fields_to_ignore.Add (e.Name);
1031 imported = Import.CreateEvent (e, declaringType, add, remove);
1033 case MemberTypes.Field:
1034 var fi = (FieldInfo) member;
1036 // Ignore compiler generated fields
1037 if (fi.IsPrivate && fi.IsDefined (typeof (CompilerGeneratedAttribute), false))
1040 if (fields_to_ignore != null && fields_to_ignore.Contains (fi.Name))
1043 imported = Import.CreateField (fi, declaringType);
1045 case MemberTypes.NestedType:
1046 Type t = (Type) member;
1048 // Ignore compiler generated types, mostly lambda containers
1049 if (t.IsNotPublic && t.IsDefined (typeof (CompilerGeneratedAttribute), false))
1052 imported = Import.CreateType (t, declaringType);
1055 throw new NotImplementedException (member.ToString ());
1058 cache.AddMember (imported);
1061 if (declaringType.IsInterface && declaringType.Interfaces != null) {
1062 foreach (var iface in declaringType.Interfaces) {
1063 cache.AddInterface (iface);
1071 class ImportedTypeParameterDefinition : ImportedMemberDefinition, ITypeDefinition
1073 public ImportedTypeParameterDefinition (Type type)
1080 public string Namespace {
1086 public int TypeParametersCount {
1092 public TypeParameterSpec[] TypeParameters {
1100 public TypeSpec GetAttributeCoClass ()
1105 public string GetAttributeDefaultMember ()
1107 throw new NotSupportedException ();
1110 public AttributeUsageAttribute GetAttributeUsage (PredefinedAttribute pa)
1112 throw new NotSupportedException ();
1115 public MemberCache LoadMembers (TypeSpec declaringType)
1117 throw new NotImplementedException ();