// // import.cs: System.Reflection conversions // // Authors: Marek Safar (marek.safar@gmail.com) // // Dual licensed under the terms of the MIT X11 or GNU GPL // // Copyright 2009, 2010 Novell, Inc // using System; using System.Reflection; using System.Runtime.CompilerServices; using System.Linq; using System.Collections.Generic; using System.Diagnostics; using System.Runtime.InteropServices; namespace Mono.CSharp { public static class Import { static Dictionary import_cache; static Dictionary type_2_predefined; public static void Initialize () { import_cache = new Dictionary (1024, ReferenceEquality.Default); // Setup mapping for predefined types type_2_predefined = new Dictionary () { { typeof (object), TypeManager.object_type }, { typeof (System.ValueType), TypeManager.value_type }, { typeof (System.Attribute), TypeManager.attribute_type }, { typeof (int), TypeManager.int32_type }, { typeof (long), TypeManager.int64_type }, { typeof (uint), TypeManager.uint32_type }, { typeof (ulong), TypeManager.uint64_type }, { typeof (byte), TypeManager.byte_type }, { typeof (sbyte), TypeManager.sbyte_type }, { typeof (short), TypeManager.short_type }, { typeof (ushort), TypeManager.ushort_type }, { typeof (System.Collections.IEnumerator), TypeManager.ienumerator_type }, { typeof (System.Collections.IEnumerable), TypeManager.ienumerable_type }, { typeof (System.IDisposable), TypeManager.idisposable_type }, { typeof (char), TypeManager.char_type }, { typeof (string), TypeManager.string_type }, { typeof (float), TypeManager.float_type }, { typeof (double), TypeManager.double_type }, { typeof (decimal), TypeManager.decimal_type }, { typeof (bool), TypeManager.bool_type }, { typeof (System.IntPtr), TypeManager.intptr_type }, { typeof (System.UIntPtr), TypeManager.uintptr_type }, { typeof (System.MulticastDelegate), TypeManager.multicast_delegate_type }, { typeof (System.Delegate), TypeManager.delegate_type }, { typeof (System.Enum), TypeManager.enum_type }, { typeof (System.Array), TypeManager.array_type }, { typeof (void), TypeManager.void_type }, { typeof (System.Type), TypeManager.type_type }, { typeof (System.Exception), TypeManager.exception_type }, { typeof (System.RuntimeFieldHandle), TypeManager.runtime_field_handle_type }, { typeof (System.RuntimeTypeHandle), TypeManager.runtime_handle_type } }; } public static FieldSpec CreateField (FieldInfo fi, TypeSpec declaringType) { Modifiers mod = 0; var fa = fi.Attributes; switch (fa & FieldAttributes.FieldAccessMask) { case FieldAttributes.Public: mod = Modifiers.PUBLIC; break; case FieldAttributes.Assembly: mod = Modifiers.INTERNAL; break; case FieldAttributes.Family: mod = Modifiers.PROTECTED; break; case FieldAttributes.FamORAssem: mod = Modifiers.PROTECTED | Modifiers.INTERNAL; break; default: mod = Modifiers.PRIVATE; break; } var definition = new ImportedMemberDefinition (fi); if ((fa & FieldAttributes.Literal) != 0) { var c = Constant.CreateConstantFromValue (ImportType (fi.FieldType), fi.GetValue (fi), Location.Null); return new ConstSpec (declaringType, definition, ImportType (fi.FieldType), fi, mod, c); } if ((fa & FieldAttributes.InitOnly) != 0) { if (fi.FieldType == typeof (decimal)) { var dc = ReadDecimalConstant (fi); if (dc != null) return new ConstSpec (declaringType, definition, ImportType (fi.FieldType), fi, mod, dc); } mod |= Modifiers.READONLY; } if ((fa & FieldAttributes.Static) != 0) mod |= Modifiers.STATIC; if (fi.FieldType.IsValueType) { if (fi.IsDefined (typeof (FixedBufferAttribute), false)) { var element_field = CreateField (fi.FieldType.GetField (FixedField.FixedElementName), declaringType); return new FixedFieldSpec (declaringType, definition, fi, element_field, mod); } } // TODO: import volatile return new FieldSpec (declaringType, definition, ImportType (fi.FieldType), fi, mod); } public static EventSpec CreateEvent (EventInfo ei, TypeSpec declaringType, MethodSpec add, MethodSpec remove) { add.IsAccessor = true; remove.IsAccessor = true; if (add.Modifiers != remove.Modifiers) throw new NotImplementedException ("Different accessor modifiers " + ei.Name); var definition = new ImportedMemberDefinition (ei); return new EventSpec (declaringType, definition, ImportType (ei.EventHandlerType), add.Modifiers, add, remove); } static T[] CreateGenericParameters (Type type, TypeSpec declaringType) where T : TypeSpec { Type[] tparams = type.GetGenericArguments (); int parent_owned_count; if (type.IsNested) { parent_owned_count = type.DeclaringType.GetGenericArguments ().Length; // // System.Reflection duplicates parent type parameters for each // nested type with slightly modified properties (eg. different owner) // This just makes things more complicated (think of cloned constraints) // therefore we remap any nested type owned by parent using `type_cache' // to the single TypeParameterSpec // if (declaringType != null && parent_owned_count > 0) { int read_count = 0; while (read_count != parent_owned_count) { var tparams_count = declaringType.Arity; if (tparams_count != 0) { var parent_tp = declaringType.MemberDefinition.TypeParameters; read_count += tparams_count; for (int i = 0; i < tparams_count; i++) { import_cache.Add (tparams[parent_owned_count - read_count + i], parent_tp[i]); } } declaringType = declaringType.DeclaringType; } } } else { parent_owned_count = 0; } if (tparams.Length - parent_owned_count == 0) return null; return CreateGenericParameters (parent_owned_count, tparams); } static T[] CreateGenericParameters (int first, Type[] tparams) where T : TypeSpec { var tspec = new T [tparams.Length - first]; for (int pos = first; pos < tparams.Length; ++pos) { tspec [pos - first] = (T) CreateType (tparams [pos]); } return tspec; } public static MethodSpec CreateMethod (MethodBase mb, TypeSpec declaringType) { Modifiers mod = ReadMethodModifiers (mb, declaringType); //if (declaringType.IsInterface) { // mod = (mod & ~Modifiers.ABSTRACT) | Modifiers.VIRTUAL; //} bool is_generic; ImportedMethodDefinition definition; var parameters = ParametersImported.Create (declaringType, mb); if (mb.IsGenericMethod) { if (!mb.IsGenericMethodDefinition) throw new NotSupportedException ("assert"); var tparams = CreateGenericParameters(0, mb.GetGenericArguments ()); definition = new ImportedGenericMethodDefinition ((MethodInfo) mb, parameters, tparams); is_generic = true; } else { definition = new ImportedMethodDefinition (mb, parameters); is_generic = false; } MemberKind kind; TypeSpec returnType; if (mb.MemberType == MemberTypes.Constructor) { kind = MemberKind.Constructor; returnType = TypeManager.void_type; } else { // // Detect operators and destructors // string name = mb.Name; kind = MemberKind.Method; if (!mb.DeclaringType.IsInterface && name.Length > 6) { if ((mod & (Modifiers.STATIC | Modifiers.PUBLIC)) == (Modifiers.STATIC | Modifiers.PUBLIC)) { if (name[2] == '_' && name[1] == 'p' && name[0] == 'o') { var op_type = Operator.GetType (name); if (op_type.HasValue) { kind = MemberKind.Operator; } } } else if (parameters.IsEmpty && name == Destructor.MetadataName) { kind = MemberKind.Destructor; } } returnType = ImportType (((MethodInfo)mb).ReturnType); } MethodSpec ms = new MethodSpec (kind, declaringType, definition, returnType, mb, parameters, mod); if (is_generic) ms.IsGeneric = true; return ms; } // // Returns null when the property is not valid C# property // public static PropertySpec CreateProperty (PropertyInfo pi, TypeSpec declaringType, MethodSpec get, MethodSpec set) { var definition = new ImportedMemberDefinition (pi); Modifiers mod = 0; AParametersCollection param = null; TypeSpec type = null; if (get != null) { mod = get.Modifiers; param = get.Parameters; type = get.ReturnType; } bool is_valid_property = true; if (set != null) { if (set.ReturnType != TypeManager.void_type) is_valid_property = false; var set_param_count = set.Parameters.Count - 1; if (set_param_count < 0) is_valid_property = false; var data = new IParameterData [set_param_count]; var types = new TypeSpec[set_param_count]; for (int i = 0; i < set_param_count; ++i ) { data[i] = set.Parameters.FixedParameters[i]; types[i] = set.Parameters.Types[i]; } var set_param = new ParametersImported (data, types); var set_type = set.Parameters.Types[set_param_count]; if (mod == 0) { mod = set.Modifiers; param = set_param; type = set_type; } else { if (set_param_count != get.Parameters.Count) is_valid_property = false; if (get.ReturnType != set_type) is_valid_property = false; // Possible custom accessor modifiers if ((mod & ~Modifiers.AccessibilityMask) != (set.Modifiers & ~Modifiers.AccessibilityMask)) { var get_acc = mod & Modifiers.AccessibilityMask; if (get_acc != Modifiers.PUBLIC) { var set_acc = set.Modifiers & Modifiers.AccessibilityMask; // If the accessor modifiers are not same, do extra restriction checks if (get_acc != set_acc) { var get_restr = ModifiersExtensions.IsRestrictedModifier (get_acc, set_acc); var set_restr = ModifiersExtensions.IsRestrictedModifier (set_acc, get_acc); if (get_restr && set_restr) { is_valid_property = false; // Neither is more restrictive } if (set_restr) { mod &= ~Modifiers.AccessibilityMask; mod |= set_acc; } } } } } } PropertySpec spec = null; if (!param.IsEmpty) { var index_name = declaringType.MemberDefinition.GetAttributeDefaultMember (); if (index_name == null) { is_valid_property = false; } else { if (get != null) { if (get.IsStatic) is_valid_property = false; if (get.Name.IndexOf (index_name, StringComparison.Ordinal) != 4) is_valid_property = false; } if (set != null) { if (set.IsStatic) is_valid_property = false; if (set.Name.IndexOf (index_name, StringComparison.Ordinal) != 4) is_valid_property = false; } } if (is_valid_property) spec = new IndexerSpec (declaringType, definition, type, param, pi, mod); } if (spec == null) spec = new PropertySpec (MemberKind.Property, declaringType, definition, type, pi, mod); if (!is_valid_property) { spec.IsNotRealProperty = true; return spec; } if (set != null) spec.Set = set; if (get != null) spec.Get = get; return spec; } public static TypeSpec CreateType (Type type) { return CreateType (type, null); } public static TypeSpec CreateType (Type type, TypeSpec declaringType) { TypeSpec spec; if (import_cache.TryGetValue (type, out spec)) return spec; if (type.IsGenericType && !type.IsGenericTypeDefinition) { var type_def = type.GetGenericTypeDefinition (); spec = CreateType (type_def, declaringType); var targs = CreateGenericParameters (type, null); InflatedTypeSpec inflated; if (targs == null) { // Inflating nested non-generic type, same in TypeSpec::InflateMember inflated = new InflatedTypeSpec (spec, declaringType, TypeSpec.EmptyTypes); } else { // CreateGenericParameters constraint could inflate type if (import_cache.ContainsKey (type)) return import_cache[type]; inflated = spec.MakeGenericType (targs); // Use of reading cache to speed up reading only import_cache.Add (type, inflated); } return inflated; } Modifiers mod; MemberKind kind; var ma = type.Attributes; switch (ma & TypeAttributes.VisibilityMask) { case TypeAttributes.Public: case TypeAttributes.NestedPublic: mod = Modifiers.PUBLIC; break; case TypeAttributes.NestedPrivate: mod = Modifiers.PRIVATE; break; case TypeAttributes.NestedFamily: mod = Modifiers.PROTECTED; break; case TypeAttributes.NestedFamORAssem: mod = Modifiers.PROTECTED | Modifiers.INTERNAL; break; default: mod = Modifiers.INTERNAL; break; } if ((ma & TypeAttributes.Interface) != 0) { kind = MemberKind.Interface; } else if (type.IsGenericParameter) { kind = MemberKind.TypeParameter; } else if (type.IsClass || type.IsAbstract) { // SRE: System.Enum returns false for IsClass if ((ma & TypeAttributes.Sealed) != 0 && type.IsSubclassOf (typeof (MulticastDelegate))) { kind = MemberKind.Delegate; } else { kind = MemberKind.Class; if (type == typeof (object)) { #if NET_4_0 var pa = PredefinedAttributes.Get.Dynamic.Type; if (pa != null && type.IsDefined (typeof (DynamicAttribute), false)) return InternalType.Dynamic; #endif } if ((ma & TypeAttributes.Sealed) != 0) { mod |= Modifiers.SEALED; if ((ma & TypeAttributes.Abstract) != 0) mod |= Modifiers.STATIC; } else if ((ma & TypeAttributes.Abstract) != 0) { mod |= Modifiers.ABSTRACT; } } } else if (type.IsEnum) { kind = MemberKind.Enum; } else { kind = MemberKind.Struct; mod |= Modifiers.SEALED; } var definition = new ImportedTypeDefinition (type); PredefinedTypeSpec pt; if (kind == MemberKind.Enum) { const BindingFlags any_member = BindingFlags.DeclaredOnly | BindingFlags.Static | BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic; var u_type = type.GetField (Enum.UnderlyingValueField, any_member); if (u_type != null) { spec = new EnumSpec (declaringType, definition, Import.CreateType (u_type.FieldType), type, mod); } } else if (kind == MemberKind.TypeParameter) { // Return as type_cache was updated return CreateTypeParameter (type, declaringType); } else if (type.IsGenericTypeDefinition) { definition.TypeParameters = CreateGenericParameters(type, declaringType); // Constraints are not loaded on demand and can reference this type if (import_cache.TryGetValue (type, out spec)) return spec; } else if (type_2_predefined.TryGetValue (type, out pt)) { spec = pt; pt.SetDefinition (definition, type); } if (spec == null) spec = new TypeSpec (kind, declaringType, definition, type, mod); import_cache.Add (type, spec); if (kind == MemberKind.Interface) spec.BaseType = TypeManager.object_type; else if (type.BaseType != null) spec.BaseType = CreateType (type.BaseType); var ifaces = type.GetInterfaces (); if (ifaces.Length > 0) { foreach (Type iface in ifaces) { spec.AddInterface (Import.CreateType (iface)); } } return spec; } static TypeParameterSpec CreateTypeParameter (Type type, TypeSpec declaringType) { Variance variance; switch (type.GenericParameterAttributes & GenericParameterAttributes.VarianceMask) { case GenericParameterAttributes.Covariant: variance = Variance.Covariant; break; case GenericParameterAttributes.Contravariant: variance = Variance.Contravariant; break; default: variance = Variance.None; break; } SpecialConstraint special = SpecialConstraint.None; var import_special = type.GenericParameterAttributes & GenericParameterAttributes.SpecialConstraintMask; if ((import_special & GenericParameterAttributes.NotNullableValueTypeConstraint) != 0) { special |= SpecialConstraint.Struct; } else if ((import_special & GenericParameterAttributes.DefaultConstructorConstraint) != 0) { special = SpecialConstraint.Constructor; } if ((import_special & GenericParameterAttributes.ReferenceTypeConstraint) != 0) { special |= SpecialConstraint.Class; } TypeParameterSpec spec; var def = new ImportedTypeParameterDefinition (type); if (type.DeclaringMethod != null) spec = new TypeParameterSpec (type.GenericParameterPosition, def, special, variance, type); else spec = new TypeParameterSpec (declaringType, type.GenericParameterPosition, def, special, variance, type); // Add it now, so any constraint can reference it and get same instance import_cache.Add (type, spec); var constraints = type.GetGenericParameterConstraints (); foreach (var ct in constraints) { // TODO MemberCache: What to do ?? if (ct.IsGenericParameter) { continue; } if (ct.IsClass) { if (ct == typeof (ValueType)) { spec.BaseType = TypeManager.value_type; } else { spec.BaseType = CreateType (ct); } continue; } spec.AddInterface (CreateType (ct)); } if (spec.BaseType == null) spec.BaseType = TypeManager.object_type; return spec; } public static TypeSpec ImportType (Type type) { if (type.HasElementType) { var element = type.GetElementType (); var spec = ImportType (element); if (type.IsArray) return ArrayContainer.MakeType (spec, type.GetArrayRank ()); if (type.IsByRef) return ReferenceContainer.MakeType (spec); if (type.IsPointer) return PointerContainer.MakeType (spec); throw new NotImplementedException ("Unknown element type " + type.ToString ()); } TypeSpec dtype; if (type.IsNested) dtype = ImportType (type.DeclaringType); else dtype = null; return CreateType (type, dtype); } // // Decimal constants cannot be encoded in the constant blob, and thus are marked // as IsInitOnly ('readonly' in C# parlance). We get its value from the // DecimalConstantAttribute metadata. // static Constant ReadDecimalConstant (FieldInfo fi) { object[] attrs = fi.GetCustomAttributes (typeof (DecimalConstantAttribute), false); if (attrs.Length != 1) return null; return new DecimalConstant (((DecimalConstantAttribute) attrs [0]).Value, Location.Null); } static Modifiers ReadMethodModifiers (MethodBase mb, TypeSpec declaringType) { Modifiers mod; var ma = mb.Attributes; switch (ma & MethodAttributes.MemberAccessMask) { case MethodAttributes.Public: mod = Modifiers.PUBLIC; break; case MethodAttributes.Assembly: mod = Modifiers.INTERNAL; break; case MethodAttributes.Family: mod = Modifiers.PROTECTED; break; case MethodAttributes.FamORAssem: mod = Modifiers.PROTECTED | Modifiers.INTERNAL; break; default: mod = Modifiers.PRIVATE; break; } if ((ma & MethodAttributes.Static) != 0) { mod |= Modifiers.STATIC; } else if ((ma & MethodAttributes.Final) != 0) { mod |= Modifiers.SEALED; } else if ((ma & MethodAttributes.Abstract) != 0 && declaringType.IsClass) { mod |= Modifiers.ABSTRACT; } // It can be sealed and override if ((ma & MethodAttributes.Virtual) != 0) { if ((ma & MethodAttributes.NewSlot) != 0 || !declaringType.IsClass || mod == Modifiers.PRIVATE) { mod |= Modifiers.VIRTUAL; } else { // Cannot set to OVERRIDE without full hierarchy checks // this flag indicates that the method could be override // but further validation is needed mod |= Modifiers.OVERRIDE_UNCHECKED; } } return mod; } } class ImportedMemberDefinition : IMemberDefinition { protected class AttributesBag { public static readonly AttributesBag Default = new AttributesBag (); public AttributeUsageAttribute AttributeUsage; public ObsoleteAttribute Obsolete; public string[] Conditionals; public string DefaultIndexerName; public bool IsNotCLSCompliant; public static AttributesBag Read (MemberInfo mi) { AttributesBag bag = null; List conditionals = null; var attrs = CustomAttributeData.GetCustomAttributes (mi); foreach (var a in attrs) { var type = a.Constructor.DeclaringType; if (type == typeof (ObsoleteAttribute)) { if (bag == null) bag = new AttributesBag (); var args = a.ConstructorArguments; if (args.Count == 1) { bag.Obsolete = new ObsoleteAttribute ((string) args[0].Value); } else if (args.Count == 2) { bag.Obsolete = new ObsoleteAttribute ((string) args[0].Value, (bool) args[1].Value); } else { bag.Obsolete = new ObsoleteAttribute (); } continue; } if (type == typeof (ConditionalAttribute)) { if (bag == null) bag = new AttributesBag (); if (conditionals == null) conditionals = new List (2); conditionals.Add ((string) a.ConstructorArguments[0].Value); continue; } if (type == typeof (CLSCompliantAttribute)) { if (bag == null) bag = new AttributesBag (); bag.IsNotCLSCompliant = !(bool) a.ConstructorArguments[0].Value; continue; } // Type only attributes if (type == typeof (DefaultMemberAttribute)) { if (bag == null) bag = new AttributesBag (); bag.DefaultIndexerName = (string) a.ConstructorArguments[0].Value; continue; } if (type == typeof (AttributeUsageAttribute)) { if (bag == null) bag = new AttributesBag (); bag.AttributeUsage = new AttributeUsageAttribute ((AttributeTargets) a.ConstructorArguments[0].Value); foreach (var named in a.NamedArguments) { if (named.MemberInfo.Name == "AllowMultiple") bag.AttributeUsage.AllowMultiple = (bool) named.TypedValue.Value; else if (named.MemberInfo.Name == "Inherited") bag.AttributeUsage.Inherited = (bool) named.TypedValue.Value; } continue; } } if (bag == null) return Default; if (conditionals != null) bag.Conditionals = conditionals.ToArray (); return bag; } } protected readonly MemberInfo provider; protected AttributesBag cattrs; public ImportedMemberDefinition (MemberInfo provider) { this.provider = provider; } #region Properties public Assembly Assembly { get { return provider.Module.Assembly; } } public bool IsImported { get { return true; } } public virtual string Name { get { return provider.Name; } } #endregion public string[] ConditionalConditions () { if (cattrs == null) ReadAttributes (); return cattrs.Conditionals; } public ObsoleteAttribute GetAttributeObsolete () { if (cattrs == null) ReadAttributes (); return cattrs.Obsolete; } public bool IsNotCLSCompliant () { if (cattrs == null) ReadAttributes (); return cattrs.IsNotCLSCompliant; } protected void ReadAttributes () { cattrs = AttributesBag.Read (provider); } public void SetIsAssigned () { // Unused for imported members } public void SetIsUsed () { // Unused for imported members } } class ImportedMethodDefinition : ImportedMemberDefinition, IParametersMember { readonly AParametersCollection parameters; public ImportedMethodDefinition (MethodBase provider, AParametersCollection parameters) : base (provider) { this.parameters = parameters; } #region Properties public AParametersCollection Parameters { get { return parameters; } } public TypeSpec MemberType { get { throw new NotImplementedException (); } } #endregion } class ImportedGenericMethodDefinition : ImportedMethodDefinition, IGenericMethodDefinition { TypeParameterSpec[] tparams; public ImportedGenericMethodDefinition (MethodInfo provider, AParametersCollection parameters, TypeParameterSpec[] tparams) : base (provider, parameters) { this.tparams = tparams; } #region Properties public TypeParameterSpec[] TypeParameters { get { return tparams; } } public int TypeParametersCount { get { return tparams.Length; } } #endregion } class ImportedTypeDefinition : ImportedMemberDefinition, ITypeDefinition { TypeParameterSpec[] tparams; string name; public ImportedTypeDefinition (Type type) : base (type) { } #region Properties public override string Name { get { if (name == null) { name = base.Name; if (tparams != null) name = name.Substring (0, name.IndexOf ('`')); } return name; } } public string Namespace { get { return ((Type) provider).Namespace; } } public int TypeParametersCount { get { return tparams == null ? 0 : tparams.Length; } } public TypeParameterSpec[] TypeParameters { get { return tparams; } set { tparams = value; } } #endregion public TypeSpec GetAttributeCoClass () { // TODO: Use ReadAttributes var attr = provider.GetCustomAttributes (typeof (CoClassAttribute), false); if (attr.Length < 1) return null; return Import.CreateType (((CoClassAttribute) attr[0]).CoClass); } public string GetAttributeDefaultMember () { if (cattrs == null) ReadAttributes (); return cattrs.DefaultIndexerName; } public AttributeUsageAttribute GetAttributeUsage (PredefinedAttribute pa) { if (cattrs == null) ReadAttributes (); return cattrs.AttributeUsage; } public MemberCache LoadMembers (TypeSpec declaringType) { var loading_type = (Type) provider; const BindingFlags all_members = BindingFlags.DeclaredOnly | BindingFlags.Static | BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic; const MethodAttributes explicit_impl = MethodAttributes.NewSlot | MethodAttributes.Virtual | MethodAttributes.HideBySig | MethodAttributes.Final | MethodAttributes.Private; Dictionary possible_accessors = null; MemberSpec imported; MethodInfo m; List fields_to_ignore = null; // // This requires methods to be returned first which seems to work for both Mono and .NET // var all = loading_type.GetMembers (all_members); var cache = new MemberCache (all.Length); foreach (var member in all) { switch (member.MemberType) { case MemberTypes.Constructor: case MemberTypes.Method: MethodBase mb = (MethodBase) member; // Ignore explicitly implemented members if ((mb.Attributes & explicit_impl) == explicit_impl) continue; // Ignore compiler generated methods if (mb.IsPrivate && mb.IsDefined (typeof (CompilerGeneratedAttribute), false)) continue; imported = Import.CreateMethod (mb, declaringType); var name = imported.Name; if (imported.Kind == MemberKind.Method && name.Length > 4) { if ((name[3] == '_' && (name.StartsWith ("get", StringComparison.Ordinal) || name.StartsWith ("set", StringComparison.Ordinal) || name.StartsWith ("add", StringComparison.Ordinal))) || name.Length > 7 && name[6] == '_' && name.StartsWith ("remove", StringComparison.Ordinal)) { if (possible_accessors == null) possible_accessors = new Dictionary (); possible_accessors.Add (mb, (MethodSpec) imported); } } break; case MemberTypes.Property: if (possible_accessors == null) continue; var p = (PropertyInfo) member; // // Links possible accessors with property // MethodSpec get, set; m = p.GetGetMethod (true); if (m == null || !possible_accessors.TryGetValue (m, out get)) get = null; m = p.GetSetMethod (true); if (m == null || !possible_accessors.TryGetValue (m, out set)) set = null; // No accessors registered (e.g. explicit implementation) if (get == null && set == null) continue; imported = Import.CreateProperty (p, declaringType, get, set); if (imported == null) continue; break; case MemberTypes.Event: if (possible_accessors == null) continue; var e = (EventInfo) member; // // Links accessors with event // MethodSpec add, remove; m = e.GetAddMethod (true); if (m == null || !possible_accessors.TryGetValue (m, out add)) add = null; m = e.GetRemoveMethod (true); if (m == null || !possible_accessors.TryGetValue (m, out remove)) remove = null; // Both accessors are required if (add == null || remove == null) continue; if (fields_to_ignore == null) fields_to_ignore = new List (); fields_to_ignore.Add (e.Name); imported = Import.CreateEvent (e, declaringType, add, remove); break; case MemberTypes.Field: var fi = (FieldInfo) member; // Ignore compiler generated fields if (fi.IsPrivate && fi.IsDefined (typeof (CompilerGeneratedAttribute), false)) continue; if (fields_to_ignore != null && fields_to_ignore.Contains (fi.Name)) continue; imported = Import.CreateField (fi, declaringType); break; case MemberTypes.NestedType: Type t = (Type) member; // Ignore compiler generated types, mostly lambda containers if (t.IsNotPublic && t.IsDefined (typeof (CompilerGeneratedAttribute), false)) continue; imported = Import.CreateType (t, declaringType); break; default: throw new NotImplementedException (member.ToString ()); } cache.AddMember (imported); } if (declaringType.IsInterface && declaringType.Interfaces != null) { foreach (var iface in declaringType.Interfaces) { cache.AddInterface (iface); } } return cache; } } class ImportedTypeParameterDefinition : ImportedMemberDefinition, ITypeDefinition { public ImportedTypeParameterDefinition (Type type) : base (type) { } #region Properties public string Namespace { get { return null; } } public int TypeParametersCount { get { return 0; } } public TypeParameterSpec[] TypeParameters { get { return null; } } #endregion public TypeSpec GetAttributeCoClass () { return null; } public string GetAttributeDefaultMember () { throw new NotSupportedException (); } public AttributeUsageAttribute GetAttributeUsage (PredefinedAttribute pa) { throw new NotSupportedException (); } public MemberCache LoadMembers (TypeSpec declaringType) { throw new NotImplementedException (); } } }