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;
218 TypeParameterSpec[] tparams;
219 ImportedMethodDefinition definition;
221 var parameters = ParametersImported.Create (declaringType, mb);
223 if (mb.IsGenericMethod) {
224 if (!mb.IsGenericMethodDefinition)
225 throw new NotSupportedException ("assert");
227 tparams = CreateGenericParameters<TypeParameterSpec>(0, mb.GetGenericArguments ());
228 definition = new ImportedGenericMethodDefinition ((MethodInfo) mb, parameters, tparams);
230 definition = new ImportedMethodDefinition (mb, parameters);
236 if (mb.MemberType == MemberTypes.Constructor) {
237 kind = MemberKind.Constructor;
238 returnType = TypeManager.void_type;
241 // Detect operators and destructors
243 string name = mb.Name;
244 kind = MemberKind.Method;
245 if (tparams == null && !mb.DeclaringType.IsInterface && name.Length > 6) {
246 if ((mod & (Modifiers.STATIC | Modifiers.PUBLIC)) == (Modifiers.STATIC | Modifiers.PUBLIC)) {
247 if (name[2] == '_' && name[1] == 'p' && name[0] == 'o') {
248 var op_type = Operator.GetType (name);
249 if (op_type.HasValue && parameters.Count > 0 && parameters.Count < 3) {
250 kind = MemberKind.Operator;
253 } else if (parameters.IsEmpty && name == Destructor.MetadataName) {
254 kind = MemberKind.Destructor;
255 if (declaringType == TypeManager.object_type) {
256 mod &= ~Modifiers.OVERRIDE;
257 mod |= Modifiers.VIRTUAL;
262 returnType = ImportType (((MethodInfo)mb).ReturnType);
264 // Cannot set to OVERRIDE without full hierarchy checks
265 // this flag indicates that the method could be override
266 // but further validation is needed
267 if ((mod & Modifiers.OVERRIDE) != 0 && kind == MemberKind.Method && declaringType.BaseType != null) {
268 var filter = MemberFilter.Method (name, tparams != null ? tparams.Length : 0, parameters, null);
269 var candidate = MemberCache.FindMember (declaringType.BaseType, filter, BindingRestriction.None);
272 // For imported class method do additional validation to be sure that metadata
273 // override flag was correct
275 // Difference between protected internal and protected is ok
277 const Modifiers conflict_mask = Modifiers.AccessibilityMask & ~Modifiers.INTERNAL;
278 if (candidate == null || (candidate.Modifiers & conflict_mask) != (mod & conflict_mask) || candidate.IsStatic) {
279 mod &= ~Modifiers.OVERRIDE;
284 MethodSpec ms = new MethodSpec (kind, declaringType, definition, returnType, mb, parameters, mod);
292 // Returns null when the property is not valid C# property
294 public static PropertySpec CreateProperty (PropertyInfo pi, TypeSpec declaringType, MethodSpec get, MethodSpec set)
296 var definition = new ImportedMemberDefinition (pi);
299 AParametersCollection param = null;
300 TypeSpec type = null;
303 param = get.Parameters;
304 type = get.ReturnType;
307 bool is_valid_property = true;
309 if (set.ReturnType != TypeManager.void_type)
310 is_valid_property = false;
312 var set_param_count = set.Parameters.Count - 1;
314 if (set_param_count < 0) {
316 is_valid_property = false;
319 var set_type = set.Parameters.Types[set_param_count];
322 AParametersCollection set_based_param;
324 if (set_param_count == 0) {
325 set_based_param = ParametersCompiled.EmptyReadOnlyParameters;
328 // Create indexer parameters based on setter method parameters (the last parameter has to be removed)
330 var data = new IParameterData[set_param_count];
331 var types = new TypeSpec[set_param_count];
332 Array.Copy (set.Parameters.FixedParameters, data, set_param_count);
333 Array.Copy (set.Parameters.Types, types, set_param_count);
334 set_based_param = new ParametersImported (data, types, set.Parameters.HasParams);
338 param = set_based_param;
341 if (set_param_count != get.Parameters.Count)
342 is_valid_property = false;
344 if (get.ReturnType != set_type)
345 is_valid_property = false;
347 // Possible custom accessor modifiers
348 if ((mod & Modifiers.AccessibilityMask) != (set.Modifiers & Modifiers.AccessibilityMask)) {
349 var get_acc = mod & Modifiers.AccessibilityMask;
350 if (get_acc != Modifiers.PUBLIC) {
351 var set_acc = set.Modifiers & Modifiers.AccessibilityMask;
352 // If the accessor modifiers are not same, do extra restriction checks
353 if (get_acc != set_acc) {
354 var get_restr = ModifiersExtensions.IsRestrictedModifier (get_acc, set_acc);
355 var set_restr = ModifiersExtensions.IsRestrictedModifier (set_acc, get_acc);
356 if (get_restr && set_restr) {
357 is_valid_property = false; // Neither is more restrictive
361 mod &= ~Modifiers.AccessibilityMask;
370 PropertySpec spec = null;
371 if (!param.IsEmpty) {
372 var index_name = declaringType.MemberDefinition.GetAttributeDefaultMember ();
373 if (index_name == null) {
374 is_valid_property = false;
378 is_valid_property = false;
379 if (get.Name.IndexOf (index_name, StringComparison.Ordinal) != 4)
380 is_valid_property = false;
384 is_valid_property = false;
385 if (set.Name.IndexOf (index_name, StringComparison.Ordinal) != 4)
386 is_valid_property = false;
390 if (is_valid_property)
391 spec = new IndexerSpec (declaringType, definition, type, param, pi, mod);
395 spec = new PropertySpec (MemberKind.Property, declaringType, definition, type, pi, mod);
397 if (!is_valid_property) {
398 spec.IsNotRealProperty = true;
410 public static TypeSpec CreateType (Type type)
412 TypeSpec declaring_type;
413 if (type.IsNested && !type.IsGenericParameter)
414 declaring_type = CreateType (type.DeclaringType);
416 declaring_type = null;
418 return CreateType (type, declaring_type);
421 public static TypeSpec CreateType (Type type, TypeSpec declaringType)
424 if (import_cache.TryGetValue (type, out spec))
427 if (type.IsGenericType && !type.IsGenericTypeDefinition) {
428 var type_def = type.GetGenericTypeDefinition ();
429 spec = CreateType (type_def, declaringType);
431 var targs = CreateGenericParameters<TypeSpec> (type, null);
433 InflatedTypeSpec inflated;
435 // Inflating nested non-generic type, same in TypeSpec::InflateMember
436 inflated = new InflatedTypeSpec (spec, declaringType, TypeSpec.EmptyTypes);
438 // CreateGenericParameters constraint could inflate type
439 if (import_cache.ContainsKey (type))
440 return import_cache[type];
442 inflated = spec.MakeGenericType (targs);
444 // Use of reading cache to speed up reading only
445 import_cache.Add (type, inflated);
454 var ma = type.Attributes;
455 switch (ma & TypeAttributes.VisibilityMask) {
456 case TypeAttributes.Public:
457 case TypeAttributes.NestedPublic:
458 mod = Modifiers.PUBLIC;
460 case TypeAttributes.NestedPrivate:
461 mod = Modifiers.PRIVATE;
463 case TypeAttributes.NestedFamily:
464 mod = Modifiers.PROTECTED;
466 case TypeAttributes.NestedFamORAssem:
467 mod = Modifiers.PROTECTED | Modifiers.INTERNAL;
470 mod = Modifiers.INTERNAL;
474 if ((ma & TypeAttributes.Interface) != 0) {
475 kind = MemberKind.Interface;
476 } else if (type.IsGenericParameter) {
477 kind = MemberKind.TypeParameter;
478 } else if (type.IsClass || type.IsAbstract) { // SRE: System.Enum returns false for IsClass
479 if ((ma & TypeAttributes.Sealed) != 0 && type.IsSubclassOf (typeof (MulticastDelegate))) {
480 kind = MemberKind.Delegate;
482 kind = MemberKind.Class;
484 if (type == typeof (object)) {
486 var pa = PredefinedAttributes.Get.Dynamic.Type;
487 if (pa != null && type.IsDefined (typeof (DynamicAttribute), false))
488 return InternalType.Dynamic;
492 if ((ma & TypeAttributes.Sealed) != 0) {
493 mod |= Modifiers.SEALED;
494 if ((ma & TypeAttributes.Abstract) != 0)
495 mod |= Modifiers.STATIC;
496 } else if ((ma & TypeAttributes.Abstract) != 0) {
497 mod |= Modifiers.ABSTRACT;
500 } else if (type.IsEnum) {
501 kind = MemberKind.Enum;
503 kind = MemberKind.Struct;
504 mod |= Modifiers.SEALED;
507 var definition = new ImportedTypeDefinition (type);
508 PredefinedTypeSpec pt;
510 if (kind == MemberKind.Enum) {
511 const BindingFlags underlying_member = BindingFlags.DeclaredOnly |
512 BindingFlags.Instance |
513 BindingFlags.Public | BindingFlags.NonPublic;
515 var type_members = type.GetFields (underlying_member);
516 foreach (var type_member in type_members) {
517 spec = new EnumSpec (declaringType, definition, Import.CreateType (type_member.FieldType), type, mod);
522 kind = MemberKind.Class;
524 } else if (kind == MemberKind.TypeParameter) {
525 // Return as type_cache was updated
526 return CreateTypeParameter (type, declaringType);
527 } else if (type.IsGenericTypeDefinition) {
528 definition.TypeParameters = CreateGenericParameters<TypeParameterSpec>(type, declaringType);
530 // Constraints are not loaded on demand and can reference this type
531 if (import_cache.TryGetValue (type, out spec))
534 } else if (type_2_predefined.TryGetValue (type, out pt)) {
536 pt.SetDefinition (definition, type);
540 spec = new TypeSpec (kind, declaringType, definition, type, mod);
542 import_cache.Add (type, spec);
544 if (kind == MemberKind.Interface)
545 spec.BaseType = TypeManager.object_type;
546 else if (type.BaseType != null)
547 spec.BaseType = CreateType (type.BaseType);
549 var ifaces = type.GetInterfaces ();
550 if (ifaces.Length > 0) {
551 foreach (Type iface in ifaces) {
552 spec.AddInterface (Import.CreateType (iface));
559 static TypeParameterSpec CreateTypeParameter (Type type, TypeSpec declaringType)
562 switch (type.GenericParameterAttributes & GenericParameterAttributes.VarianceMask) {
563 case GenericParameterAttributes.Covariant:
564 variance = Variance.Covariant;
566 case GenericParameterAttributes.Contravariant:
567 variance = Variance.Contravariant;
570 variance = Variance.None;
574 SpecialConstraint special = SpecialConstraint.None;
575 var import_special = type.GenericParameterAttributes & GenericParameterAttributes.SpecialConstraintMask;
577 if ((import_special & GenericParameterAttributes.NotNullableValueTypeConstraint) != 0) {
578 special |= SpecialConstraint.Struct;
579 } else if ((import_special & GenericParameterAttributes.DefaultConstructorConstraint) != 0) {
580 special = SpecialConstraint.Constructor;
583 if ((import_special & GenericParameterAttributes.ReferenceTypeConstraint) != 0) {
584 special |= SpecialConstraint.Class;
587 TypeParameterSpec spec;
588 var def = new ImportedTypeParameterDefinition (type);
589 if (type.DeclaringMethod != null)
590 spec = new TypeParameterSpec (type.GenericParameterPosition, def, special, variance, type);
592 spec = new TypeParameterSpec (declaringType, type.GenericParameterPosition, def, special, variance, type);
594 // Add it now, so any constraint can reference it and get same instance
595 import_cache.Add (type, spec);
597 var constraints = type.GetGenericParameterConstraints ();
598 foreach (var ct in constraints) {
599 // TODO MemberCache: What to do ??
600 if (ct.IsGenericParameter) {
605 if (ct == typeof (ValueType)) {
606 spec.BaseType = TypeManager.value_type;
608 spec.BaseType = CreateType (ct);
614 spec.AddInterface (CreateType (ct));
617 if (spec.BaseType == null)
618 spec.BaseType = TypeManager.object_type;
623 public static TypeSpec ImportType (Type type)
625 if (type.HasElementType) {
626 var element = type.GetElementType ();
627 var spec = ImportType (element);
630 return ArrayContainer.MakeType (spec, type.GetArrayRank ());
632 return ReferenceContainer.MakeType (spec);
634 return PointerContainer.MakeType (spec);
636 throw new NotImplementedException ("Unknown element type " + type.ToString ());
641 dtype = ImportType (type.DeclaringType);
645 return CreateType (type, dtype);
649 // Decimal constants cannot be encoded in the constant blob, and thus are marked
650 // as IsInitOnly ('readonly' in C# parlance). We get its value from the
651 // DecimalConstantAttribute metadata.
653 static Constant ReadDecimalConstant (FieldInfo fi)
655 object[] attrs = fi.GetCustomAttributes (typeof (DecimalConstantAttribute), false);
656 if (attrs.Length != 1)
659 return new DecimalConstant (((DecimalConstantAttribute) attrs [0]).Value, Location.Null);
662 static Modifiers ReadMethodModifiers (MethodBase mb, TypeSpec declaringType)
665 var ma = mb.Attributes;
666 switch (ma & MethodAttributes.MemberAccessMask) {
667 case MethodAttributes.Public:
668 mod = Modifiers.PUBLIC;
670 case MethodAttributes.Assembly:
671 mod = Modifiers.INTERNAL;
673 case MethodAttributes.Family:
674 mod = Modifiers.PROTECTED;
676 case MethodAttributes.FamORAssem:
677 mod = Modifiers.PROTECTED | Modifiers.INTERNAL;
680 mod = Modifiers.PRIVATE;
684 if ((ma & MethodAttributes.Static) != 0) {
685 mod |= Modifiers.STATIC;
688 if ((ma & MethodAttributes.Abstract) != 0 && declaringType.IsClass) {
689 mod |= Modifiers.ABSTRACT;
693 if ((ma & MethodAttributes.Final) != 0)
694 mod |= Modifiers.SEALED;
696 // It can be sealed and override
697 if ((ma & MethodAttributes.Virtual) != 0) {
698 if ((ma & MethodAttributes.NewSlot) != 0 || !declaringType.IsClass || mod == Modifiers.PRIVATE) {
699 mod |= Modifiers.VIRTUAL;
701 mod |= Modifiers.OVERRIDE;
709 class ImportedMemberDefinition : IMemberDefinition
711 protected class AttributesBag
713 public static readonly AttributesBag Default = new AttributesBag ();
715 public AttributeUsageAttribute AttributeUsage;
716 public ObsoleteAttribute Obsolete;
717 public string[] Conditionals;
718 public string DefaultIndexerName;
719 public bool IsNotCLSCompliant;
721 public static AttributesBag Read (MemberInfo mi)
723 AttributesBag bag = null;
724 List<string> conditionals = null;
726 var attrs = CustomAttributeData.GetCustomAttributes (mi);
727 foreach (var a in attrs) {
728 var type = a.Constructor.DeclaringType;
729 if (type == typeof (ObsoleteAttribute)) {
731 bag = new AttributesBag ();
733 var args = a.ConstructorArguments;
735 if (args.Count == 1) {
736 bag.Obsolete = new ObsoleteAttribute ((string) args[0].Value);
737 } else if (args.Count == 2) {
738 bag.Obsolete = new ObsoleteAttribute ((string) args[0].Value, (bool) args[1].Value);
740 bag.Obsolete = new ObsoleteAttribute ();
746 if (type == typeof (ConditionalAttribute)) {
748 bag = new AttributesBag ();
750 if (conditionals == null)
751 conditionals = new List<string> (2);
753 conditionals.Add ((string) a.ConstructorArguments[0].Value);
757 if (type == typeof (CLSCompliantAttribute)) {
759 bag = new AttributesBag ();
761 bag.IsNotCLSCompliant = !(bool) a.ConstructorArguments[0].Value;
765 // Type only attributes
766 if (type == typeof (DefaultMemberAttribute)) {
768 bag = new AttributesBag ();
770 bag.DefaultIndexerName = (string) a.ConstructorArguments[0].Value;
774 if (type == typeof (AttributeUsageAttribute)) {
776 bag = new AttributesBag ();
778 bag.AttributeUsage = new AttributeUsageAttribute ((AttributeTargets) a.ConstructorArguments[0].Value);
779 foreach (var named in a.NamedArguments) {
780 if (named.MemberInfo.Name == "AllowMultiple")
781 bag.AttributeUsage.AllowMultiple = (bool) named.TypedValue.Value;
782 else if (named.MemberInfo.Name == "Inherited")
783 bag.AttributeUsage.Inherited = (bool) named.TypedValue.Value;
792 if (conditionals != null)
793 bag.Conditionals = conditionals.ToArray ();
799 protected readonly MemberInfo provider;
800 protected AttributesBag cattrs;
802 public ImportedMemberDefinition (MemberInfo provider)
804 this.provider = provider;
809 public Assembly Assembly {
811 return provider.Module.Assembly;
815 public bool IsImported {
821 public virtual string Name {
823 return provider.Name;
829 public string[] ConditionalConditions ()
834 return cattrs.Conditionals;
837 public ObsoleteAttribute GetAttributeObsolete ()
842 return cattrs.Obsolete;
845 public bool IsNotCLSCompliant ()
850 return cattrs.IsNotCLSCompliant;
853 protected void ReadAttributes ()
855 cattrs = AttributesBag.Read (provider);
858 public void SetIsAssigned ()
860 // Unused for imported members
863 public void SetIsUsed ()
865 // Unused for imported members
869 class ImportedMethodDefinition : ImportedMemberDefinition, IParametersMember
871 readonly AParametersCollection parameters;
873 public ImportedMethodDefinition (MethodBase provider, AParametersCollection parameters)
876 this.parameters = parameters;
881 public AParametersCollection Parameters {
887 public TypeSpec MemberType {
889 throw new NotImplementedException ();
896 class ImportedGenericMethodDefinition : ImportedMethodDefinition, IGenericMethodDefinition
898 TypeParameterSpec[] tparams;
900 public ImportedGenericMethodDefinition (MethodInfo provider, AParametersCollection parameters, TypeParameterSpec[] tparams)
901 : base (provider, parameters)
903 this.tparams = tparams;
908 public TypeParameterSpec[] TypeParameters {
914 public int TypeParametersCount {
916 return tparams.Length;
923 class ImportedTypeDefinition : ImportedMemberDefinition, ITypeDefinition
925 TypeParameterSpec[] tparams;
928 public ImportedTypeDefinition (Type type)
935 public override string Name {
940 name = name.Substring (0, name.IndexOf ('`'));
947 public string Namespace {
949 return ((Type) provider).Namespace;
953 public int TypeParametersCount {
955 return tparams == null ? 0 : tparams.Length;
959 public TypeParameterSpec[] TypeParameters {
970 public TypeSpec GetAttributeCoClass ()
972 // TODO: Use ReadAttributes
973 var attr = provider.GetCustomAttributes (typeof (CoClassAttribute), false);
977 return Import.CreateType (((CoClassAttribute) attr[0]).CoClass);
980 public string GetAttributeDefaultMember ()
985 return cattrs.DefaultIndexerName;
988 public AttributeUsageAttribute GetAttributeUsage (PredefinedAttribute pa)
993 return cattrs.AttributeUsage;
996 public MemberCache LoadMembers (TypeSpec declaringType)
998 var loading_type = (Type) provider;
999 const BindingFlags all_members = BindingFlags.DeclaredOnly |
1000 BindingFlags.Static | BindingFlags.Instance |
1001 BindingFlags.Public | BindingFlags.NonPublic;
1003 const MethodAttributes explicit_impl = MethodAttributes.NewSlot |
1004 MethodAttributes.Virtual | MethodAttributes.HideBySig |
1005 MethodAttributes.Final;
1007 Dictionary<MethodBase, MethodSpec> possible_accessors = null;
1008 MemberSpec imported;
1012 // This requires methods to be returned first which seems to work for both Mono and .NET
1016 all = loading_type.GetMembers (all_members);
1017 } catch (Exception e) {
1018 throw new InternalErrorException (e, "Could not import type `{0}' from `{1}'",
1019 declaringType.GetSignatureForError (), declaringType.Assembly.Location);
1022 var cache = new MemberCache (all.Length);
1023 foreach (var member in all) {
1024 switch (member.MemberType) {
1025 case MemberTypes.Constructor:
1026 case MemberTypes.Method:
1027 MethodBase mb = (MethodBase) member;
1029 // Ignore explicitly implemented members
1030 if ((mb.Attributes & explicit_impl) == explicit_impl && (mb.Attributes & MethodAttributes.MemberAccessMask) == MethodAttributes.Private)
1033 // Ignore compiler generated methods
1034 if (mb.IsPrivate && mb.IsDefined (typeof (CompilerGeneratedAttribute), false))
1037 imported = Import.CreateMethod (mb, declaringType);
1038 if (imported.Kind == MemberKind.Method && !imported.IsGeneric) {
1039 if (possible_accessors == null)
1040 possible_accessors = new Dictionary<MethodBase, MethodSpec> (ReferenceEquality<MethodBase>.Default);
1042 // There are no metadata rules for accessors, we have to consider any method as possible candidate
1043 possible_accessors.Add (mb, (MethodSpec) imported);
1047 case MemberTypes.Property:
1048 if (possible_accessors == null)
1051 var p = (PropertyInfo) member;
1053 // Links possible accessors with property
1055 MethodSpec get, set;
1056 m = p.GetGetMethod (true);
1057 if (m == null || !possible_accessors.TryGetValue (m, out get))
1060 m = p.GetSetMethod (true);
1061 if (m == null || !possible_accessors.TryGetValue (m, out set))
1064 // No accessors registered (e.g. explicit implementation)
1065 if (get == null && set == null)
1068 imported = Import.CreateProperty (p, declaringType, get, set);
1069 if (imported == null)
1073 case MemberTypes.Event:
1074 if (possible_accessors == null)
1077 var e = (EventInfo) member;
1079 // Links accessors with event
1081 MethodSpec add, remove;
1082 m = e.GetAddMethod (true);
1083 if (m == null || !possible_accessors.TryGetValue (m, out add))
1086 m = e.GetRemoveMethod (true);
1087 if (m == null || !possible_accessors.TryGetValue (m, out remove))
1090 // Both accessors are required
1091 if (add == null || remove == null)
1094 imported = Import.CreateEvent (e, declaringType, add, remove);
1096 case MemberTypes.Field:
1097 var fi = (FieldInfo) member;
1099 // Ignore compiler generated fields
1100 if (fi.IsPrivate && fi.IsDefined (typeof (CompilerGeneratedAttribute), false))
1103 imported = Import.CreateField (fi, declaringType);
1104 if (imported == null)
1108 case MemberTypes.NestedType:
1109 Type t = (Type) member;
1111 // Ignore compiler generated types, mostly lambda containers
1112 if (t.IsNotPublic && t.IsDefined (typeof (CompilerGeneratedAttribute), false))
1115 imported = Import.CreateType (t, declaringType);
1118 throw new NotImplementedException (member.ToString ());
1121 cache.AddMember (imported);
1124 if (declaringType.IsInterface && declaringType.Interfaces != null) {
1125 foreach (var iface in declaringType.Interfaces) {
1126 cache.AddInterface (iface);
1134 class ImportedTypeParameterDefinition : ImportedMemberDefinition, ITypeDefinition
1136 public ImportedTypeParameterDefinition (Type type)
1143 public string Namespace {
1149 public int TypeParametersCount {
1155 public TypeParameterSpec[] TypeParameters {
1163 public TypeSpec GetAttributeCoClass ()
1168 public string GetAttributeDefaultMember ()
1170 throw new NotSupportedException ();
1173 public AttributeUsageAttribute GetAttributeUsage (PredefinedAttribute pa)
1175 throw new NotSupportedException ();
1178 public MemberCache LoadMembers (TypeSpec declaringType)
1180 throw new NotImplementedException ();