namespace Mono.CSharp
{
- public static class Import
+ public class ReflectionMetaImporter
{
- static Dictionary<Type, TypeSpec> import_cache;
- static Dictionary<Type, PredefinedTypeSpec> type_2_predefined;
+ Dictionary<Type, TypeSpec> import_cache;
+ Dictionary<Type, PredefinedTypeSpec> type_2_predefined;
- public static void Initialize ()
+ public ReflectionMetaImporter ()
{
import_cache = new Dictionary<Type, TypeSpec> (1024, ReferenceEquality<Type>.Default);
+ IgnorePrivateMembers = true;
+ }
+
+ #region Properties
+
+ public bool IgnorePrivateMembers { get; set; }
+ #endregion
+
+ public void Initialize ()
+ {
// Setup mapping for predefined types
type_2_predefined = new Dictionary<Type, PredefinedTypeSpec> () {
{ typeof (object), TypeManager.object_type },
};
}
- public static FieldSpec CreateField (FieldInfo fi, TypeSpec declaringType)
+ public FieldSpec CreateField (FieldInfo fi, TypeSpec declaringType)
{
Modifiers mod = 0;
var fa = fi.Attributes;
mod = Modifiers.PROTECTED | Modifiers.INTERNAL;
break;
default:
+ // Ignore private fields (even for error reporting) to not require extra dependencies
+ if (IgnorePrivateMembers || fi.IsDefined (typeof (CompilerGeneratedAttribute), false))
+ return null;
+
mod = Modifiers.PRIVATE;
break;
}
- // Ignore private fields (even for error reporting) to not require extra dependencies
- if (mod == Modifiers.PRIVATE)
- return null;
-
var definition = new ImportedMemberDefinition (fi);
TypeSpec field_type;
try {
- field_type = ImportType (fi.FieldType);
+ field_type = ImportType (fi.FieldType, fi, 0);
} catch (Exception e) {
// TODO: I should construct fake TypeSpec based on TypeRef signature
// but there is no way to do it with System.Reflection
- throw new InternalErrorException (e, "Cannot import field `{0}.{1}' in assembly `{2}'",
+ throw new InternalErrorException (e, "Cannot import field `{0}.{1}' referenced in assembly `{2}'",
declaringType.GetSignatureForError (), fi.Name, declaringType.Assembly);
}
return new FieldSpec (declaringType, definition, field_type, fi, mod);
}
- public static EventSpec CreateEvent (EventInfo ei, TypeSpec declaringType, MethodSpec add, MethodSpec remove)
+ public EventSpec CreateEvent (EventInfo ei, TypeSpec declaringType, MethodSpec add, MethodSpec remove)
{
add.IsAccessor = true;
remove.IsAccessor = true;
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);
+ return new EventSpec (declaringType, definition, ImportType (ei.EventHandlerType, ei, 0), add.Modifiers, add, remove);
}
- static T[] CreateGenericParameters<T> (Type type, TypeSpec declaringType) where T : TypeSpec
+ T[] CreateGenericParameters<T> (Type type, TypeSpec declaringType) where T : TypeSpec
{
Type[] tparams = type.GetGenericArguments ();
if (tparams.Length - parent_owned_count == 0)
return null;
- return CreateGenericParameters<T> (parent_owned_count, tparams);
+ return CreateGenericParameters<T> (parent_owned_count, tparams, null, 0);
}
- static T[] CreateGenericParameters<T> (int first, Type[] tparams) where T : TypeSpec
+ T[] CreateGenericParameters<T> (int first, Type[] tparams, ICustomAttributeProvider ca, int dynamicCursor) where T : TypeSpec
{
var tspec = new T [tparams.Length - first];
for (int pos = first; pos < tparams.Length; ++pos) {
var type = tparams[pos];
+ int index = pos - first;
+
if (type.HasElementType) {
var element = type.GetElementType ();
- var spec = CreateType (element);
+ var spec = ImportType (element);
if (type.IsArray) {
- tspec[pos - first] = (T) (TypeSpec) ArrayContainer.MakeType (spec, type.GetArrayRank ());
+ tspec[index] = (T) (TypeSpec) ArrayContainer.MakeType (spec, type.GetArrayRank ());
continue;
}
throw new NotImplementedException ("Unknown element type " + type.ToString ());
}
- tspec [pos - first] = (T) CreateType (type);
+ tspec [index] = (T) CreateType (type, ca, dynamicCursor + index + 1, true);
}
return tspec;
}
- public static MethodSpec CreateMethod (MethodBase mb, TypeSpec declaringType)
+ public MethodSpec CreateMethod (MethodBase mb, TypeSpec declaringType)
{
Modifiers mod = ReadMethodModifiers (mb, declaringType);
TypeParameterSpec[] tparams;
ImportedMethodDefinition definition;
- var parameters = ParametersImported.Create (declaringType, mb);
+ var parameters = CreateParameters (declaringType, mb.GetParameters (), mb);
if (mb.IsGenericMethod) {
if (!mb.IsGenericMethodDefinition)
throw new NotSupportedException ("assert");
- tparams = CreateGenericParameters<TypeParameterSpec>(0, mb.GetGenericArguments ());
+ tparams = CreateGenericParameters<TypeParameterSpec>(0, mb.GetGenericArguments (), null, 0);
definition = new ImportedGenericMethodDefinition ((MethodInfo) mb, parameters, tparams);
} else {
definition = new ImportedMethodDefinition (mb, parameters);
}
}
- returnType = ImportType (((MethodInfo)mb).ReturnType);
+ var mi = (MethodInfo) mb;
+ returnType = ImportType (mi.ReturnType, mi.ReturnTypeCustomAttributes, 0);
// Cannot set to OVERRIDE without full hierarchy checks
// this flag indicates that the method could be override
}
//
- // Returns null when the property is not valid C# property
+ // Imports System.Reflection parameters
//
- public static PropertySpec CreateProperty (PropertyInfo pi, TypeSpec declaringType, MethodSpec get, MethodSpec set)
+ AParametersCollection CreateParameters (TypeSpec parent, ParameterInfo[] pi, MethodBase method)
{
- var definition = new ImportedMemberDefinition (pi);
+ int varargs = method != null && (method.CallingConvention & CallingConventions.VarArgs) != 0 ? 1 : 0;
+
+ if (pi.Length == 0 && varargs == 0)
+ return ParametersCompiled.EmptyReadOnlyParameters;
+
+ TypeSpec[] types = new TypeSpec[pi.Length + varargs];
+ IParameterData[] par = new IParameterData[pi.Length + varargs];
+ bool is_params = false;
+ for (int i = 0; i < pi.Length; i++) {
+ ParameterInfo p = pi[i];
+ Parameter.Modifier mod = 0;
+ Expression default_value = null;
+ if (p.ParameterType.IsByRef) {
+ if ((p.Attributes & (ParameterAttributes.Out | ParameterAttributes.In)) == ParameterAttributes.Out)
+ mod = Parameter.Modifier.OUT;
+ else
+ mod = Parameter.Modifier.REF;
+
+ //
+ // Strip reference wrapping
+ //
+ var el = p.ParameterType.GetElementType ();
+ types[i] = ImportType (el, p, 0); // TODO: 1 to be csc compatible
+ } else if (i == 0 && method.IsStatic && parent.IsStatic && // TODO: parent.Assembly.IsExtension &&
+ HasExtensionAttribute (CustomAttributeData.GetCustomAttributes (method)) != null) {
+ mod = Parameter.Modifier.This;
+ types[i] = ImportType (p.ParameterType);
+ } else {
+ types[i] = ImportType (p.ParameterType, p, 0);
+
+ if (i >= pi.Length - 2 && types[i] is ArrayContainer) {
+ var cattrs = CustomAttributeData.GetCustomAttributes (p);
+ if (cattrs != null && cattrs.Any (l => l.Constructor.DeclaringType == typeof (ParamArrayAttribute))) {
+ mod = Parameter.Modifier.PARAMS;
+ is_params = true;
+ }
+ }
+
+ if (!is_params && p.IsOptional) {
+ object value = p.DefaultValue;
+ var ptype = types[i];
+ if (((p.Attributes & ParameterAttributes.HasDefault) != 0 && ptype.Kind != MemberKind.TypeParameter) || p.IsDefined (typeof (DecimalConstantAttribute), false)) {
+ var dtype = value == null ? ptype : ImportType (value.GetType ());
+ default_value = Constant.CreateConstant (null, dtype, value, Location.Null);
+ } else if (value == Missing.Value) {
+ default_value = EmptyExpression.MissingValue;
+ } else {
+ default_value = new DefaultValueExpression (new TypeExpression (ptype, Location.Null), Location.Null);
+ }
+ }
+ }
+
+ par[i] = new ParameterData (p.Name, mod, default_value);
+ }
+
+ if (varargs != 0) {
+ par[par.Length - 1] = new ArglistParameter (Location.Null);
+ types[types.Length - 1] = InternalType.Arglist;
+ }
+ return method != null ?
+ new ParametersImported (par, types, varargs != 0, is_params) :
+ new ParametersImported (par, types, is_params);
+ }
+
+
+ //
+ // Returns null when the property is not valid C# property
+ //
+ public PropertySpec CreateProperty (PropertyInfo pi, TypeSpec declaringType, MethodSpec get, MethodSpec set)
+ {
Modifiers mod = 0;
AParametersCollection param = null;
TypeSpec type = null;
}
if (is_valid_property)
- spec = new IndexerSpec (declaringType, definition, type, param, pi, mod);
+ spec = new IndexerSpec (declaringType, new ImportedIndexerDefinition (pi, param), type, param, pi, mod);
}
if (spec == null)
- spec = new PropertySpec (MemberKind.Property, declaringType, definition, type, pi, mod);
+ spec = new PropertySpec (MemberKind.Property, declaringType, new ImportedMemberDefinition (pi), type, pi, mod);
if (!is_valid_property) {
spec.IsNotRealProperty = true;
return spec;
}
- public static TypeSpec CreateType (Type type)
+ public TypeSpec CreateType (Type type)
+ {
+ return CreateType (type, null, 0, true);
+ }
+
+ TypeSpec CreateType (Type type, ICustomAttributeProvider ca, int dynamicCursor, bool canImportBaseType)
{
TypeSpec declaring_type;
if (type.IsNested && !type.IsGenericParameter)
- declaring_type = CreateType (type.DeclaringType);
+ declaring_type = CreateType (type.DeclaringType, type.DeclaringType, 0, true);
else
declaring_type = null;
- return CreateType (type, declaring_type);
+ return CreateType (type, declaring_type, ca, dynamicCursor, canImportBaseType);
}
- public static TypeSpec CreateType (Type type, TypeSpec declaringType)
+ public TypeSpec CreateType (Type type, TypeSpec declaringType, ICustomAttributeProvider ca, int dynamicCursor, bool canImportBaseType)
{
TypeSpec spec;
- if (import_cache.TryGetValue (type, out spec))
- return spec;
+ if (import_cache.TryGetValue (type, out spec)) {
+ if (ca == null)
+ return spec;
+
+ if (type == typeof (object)) {
+ if (IsDynamicType (ca, dynamicCursor))
+ return InternalType.Dynamic;
+
+ return spec;
+ }
+
+ if (!spec.IsGeneric)
+ return spec;
+
+#if NET_4_0
+ if (!ca.IsDefined (typeof (DynamicAttribute), false))
+#endif
+ return spec;
+
+ // We've found same object in the cache but this one has a dynamic custom attribute
+ // and it's most likely dynamic version of same type IFoo<object> agains IFoo<dynamic>
+ // Do resolve the type process again in that case
+ }
if (type.IsGenericType && !type.IsGenericTypeDefinition) {
var type_def = type.GetGenericTypeDefinition ();
- spec = CreateType (type_def, declaringType);
+ var targs = CreateGenericParameters<TypeSpec> (0, type.GetGenericArguments (), ca, dynamicCursor);
+ if (declaringType == null) {
+ // Simple case, no nesting
+ spec = CreateType (type_def, null, null, 0, canImportBaseType);
+ spec = spec.MakeGenericType (targs);
+ } else {
+ //
+ // Nested type case, converting .NET types like
+ // A`1.B`1.C`1<int, long, string> to typespec like
+ // A<int>.B<long>.C<string>
+ //
+ var nested_hierarchy = new List<TypeSpec> ();
+ while (declaringType.IsNested) {
+ nested_hierarchy.Add (declaringType);
+ declaringType = declaringType.DeclaringType;
+ }
- var targs = CreateGenericParameters<TypeSpec> (type, null);
+ int targs_pos = 0;
+ if (declaringType.Arity > 0) {
+ spec = declaringType.MakeGenericType (targs.Skip (targs_pos).Take (declaringType.Arity).ToArray ());
+ targs_pos = spec.Arity;
+ } else {
+ spec = declaringType;
+ }
- 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];
+ for (int i = nested_hierarchy.Count; i != 0; --i) {
+ var t = nested_hierarchy [i - 1];
+ spec = MemberCache.FindNestedType (spec, t.Name, t.Arity);
+ if (t.Arity > 0) {
+ spec = spec.MakeGenericType (targs.Skip (targs_pos).Take (spec.Arity).ToArray ());
+ targs_pos += t.Arity;
+ }
+ }
+
+ string name = type.Name;
+ int index = name.IndexOf ('`');
+ if (index > 0)
+ name = name.Substring (0, index);
- inflated = spec.MakeGenericType (targs);
+ spec = MemberCache.FindNestedType (spec, name, targs.Length - targs_pos);
+ if (spec.Arity > 0) {
+ spec = spec.MakeGenericType (targs.Skip (targs_pos).ToArray ());
+ }
+ }
- // Use of reading cache to speed up reading only
- import_cache.Add (type, inflated);
+ // Don't add generic type with dynamic arguments, they can interfere with same type
+ // using object type arguments
+ if (!spec.HasDynamicElement) {
+
+ // Add to reading cache to speed up reading
+ if (!import_cache.ContainsKey (type))
+ import_cache.Add (type, spec);
}
- return inflated;
+ return spec;
}
Modifiers mod;
kind = MemberKind.Interface;
} else if (type.IsGenericParameter) {
kind = MemberKind.TypeParameter;
- } else if (type.IsClass || type.IsAbstract) { // SRE: System.Enum returns false for IsClass
+ } else if (type.IsClass || type.IsAbstract) { // System.Reflection: System.Enum returns false for IsClass
if ((ma & TypeAttributes.Sealed) != 0 && type.IsSubclassOf (typeof (MulticastDelegate))) {
kind = MemberKind.Delegate;
mod |= Modifiers.SEALED;
} 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.SEALED;
}
- var definition = new ImportedTypeDefinition (type);
+ var definition = new ImportedTypeDefinition (this, type);
PredefinedTypeSpec pt;
if (kind == MemberKind.Enum) {
var type_members = type.GetFields (underlying_member);
foreach (var type_member in type_members) {
- spec = new EnumSpec (declaringType, definition, Import.CreateType (type_member.FieldType), type, mod);
+ spec = new EnumSpec (declaringType, definition, CreateType (type_member.FieldType), type, mod);
break;
}
import_cache.Add (type, spec);
- if (kind == MemberKind.Interface)
+ //
+ // Two stage setup as the base type can be inflated declaring type or
+ // another nested type inside same declaring type which has not been
+ // loaded, therefore we can import a base type of nested types once
+ // the types have been imported
+ //
+ if (canImportBaseType)
+ ImportTypeBase (spec, type);
+
+ return spec;
+ }
+
+ public void ImportTypeBase (Type type)
+ {
+ TypeSpec spec = import_cache[type];
+ if (spec != null)
+ ImportTypeBase (spec, type);
+ }
+
+ void ImportTypeBase (TypeSpec spec, Type type)
+ {
+ if (spec.Kind == MemberKind.Interface)
spec.BaseType = TypeManager.object_type;
- else if (type.BaseType != null)
- spec.BaseType = CreateType (type.BaseType);
+ else if (type.BaseType != null) {
+ if (type.BaseType.IsGenericType)
+ spec.BaseType = CreateType (type.BaseType, type, 0, true);
+ else
+ spec.BaseType = CreateType (type.BaseType);
+ }
var ifaces = type.GetInterfaces ();
if (ifaces.Length > 0) {
foreach (Type iface in ifaces) {
- spec.AddInterface (Import.CreateType (iface));
+ spec.AddInterface (CreateType (iface));
}
}
-
- return spec;
}
- static TypeParameterSpec CreateTypeParameter (Type type, TypeSpec declaringType)
+ TypeParameterSpec CreateTypeParameter (Type type, TypeSpec declaringType)
{
Variance variance;
switch (type.GenericParameterAttributes & GenericParameterAttributes.VarianceMask) {
return spec;
}
- public static TypeSpec ImportType (Type type)
+ static Type HasExtensionAttribute (IList<CustomAttributeData> attributes)
+ {
+ foreach (var attr in attributes) {
+ var dt = attr.Constructor.DeclaringType;
+ if (dt.Name == "ExtensionAttribute" && dt.Namespace == "System.Runtime.CompilerServices") {
+ return dt;
+ }
+ }
+
+ return null;
+ }
+
+ public void ImportAssembly (Assembly assembly, Namespace targetNamespace)
+ {
+ Type extension_type = HasExtensionAttribute (CustomAttributeData.GetCustomAttributes (assembly));
+
+ //
+ // This part tries to simulate loading of top-level
+ // types only, any missing dependencies are ignores here.
+ // Full error report is reported later when the type is
+ // actually used
+ //
+ Type[] all_types;
+ try {
+ all_types = assembly.GetTypes ();
+ } catch (ReflectionTypeLoadException e) {
+ all_types = e.Types;
+ }
+
+ ImportTypes (all_types, targetNamespace, extension_type);
+ }
+
+ public void ImportModule (Module module, Namespace targetNamespace)
+ {
+ Type extension_type = HasExtensionAttribute (CustomAttributeData.GetCustomAttributes (module));
+
+ Type[] all_types;
+ try {
+ all_types = module.GetTypes ();
+ } catch (ReflectionTypeLoadException e) {
+ all_types = e.Types;
+ throw;
+ }
+
+ ImportTypes (all_types, targetNamespace, extension_type);
+ }
+
+ void ImportTypes (Type[] types, Namespace targetNamespace, Type extension_type)
+ {
+ Namespace ns = targetNamespace;
+ string prev_namespace = null;
+ foreach (var t in types) {
+ if (t == null)
+ continue;
+
+ // Be careful not to trigger full parent type loading
+ if (t.MemberType == MemberTypes.NestedType)
+ continue;
+
+ if (t.Name[0] == '<')
+ continue;
+
+ var it = CreateType (t, null, t, 0, true);
+ if (it == null)
+ continue;
+
+ if (prev_namespace != t.Namespace) {
+ ns = t.Namespace == null ? targetNamespace : targetNamespace.GetNamespace (t.Namespace, true);
+ prev_namespace = t.Namespace;
+ }
+
+ ns.AddType (it);
+
+ if (it.IsStatic && extension_type != null && t.IsDefined (extension_type, false)) {
+ it.SetExtensionMethodContainer ();
+ }
+ }
+ }
+
+ public TypeSpec ImportType (Type type)
+ {
+ return ImportType (type, null, 0);
+ }
+
+ public TypeSpec ImportType (Type type, ICustomAttributeProvider ca, int dynamicCursor)
{
if (type.HasElementType) {
var element = type.GetElementType ();
- var spec = ImportType (element);
+ var spec = ImportType (element, ca, dynamicCursor + 1);
if (type.IsArray)
return ArrayContainer.MakeType (spec, type.GetArrayRank ());
throw new NotImplementedException ("Unknown element type " + type.ToString ());
}
- TypeSpec dtype;
- if (type.IsNested)
- dtype = ImportType (type.DeclaringType);
- else
- dtype = null;
+ return CreateType (type, ca, dynamicCursor, true);
+ }
+
+ static bool IsDynamicType (ICustomAttributeProvider ca, int index)
+ {
+#if NET_4_0
+ if (ca.IsDefined (typeof (DynamicAttribute), false)) {
+ if (index == 0)
+ return true;
- return CreateType (type, dtype);
+ var v = (DynamicAttribute) ca.GetCustomAttributes (typeof (DynamicAttribute), false)[0];
+ return v.TransformFlags[index];
+ }
+#endif
+ return false;
}
//
// as IsInitOnly ('readonly' in C# parlance). We get its value from the
// DecimalConstantAttribute metadata.
//
- static Constant ReadDecimalConstant (FieldInfo fi)
+ static Constant ReadDecimalConstant (ICustomAttributeProvider fi)
{
object[] attrs = fi.GetCustomAttributes (typeof (DecimalConstantAttribute), false);
if (attrs.Length != 1)
#endregion
}
+ class ImportedIndexerDefinition : ImportedMemberDefinition, IParametersMember
+ {
+ readonly AParametersCollection parameters;
+
+ public ImportedIndexerDefinition (PropertyInfo 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;
{
TypeParameterSpec[] tparams;
string name;
+ ReflectionMetaImporter meta_import;
- public ImportedTypeDefinition (Type type)
+ public ImportedTypeDefinition (ReflectionMetaImporter metaImport, Type type)
: base (type)
{
+ this.meta_import = metaImport;
}
#region Properties
if (attr.Length < 1)
return null;
- return Import.CreateType (((CoClassAttribute) attr[0]).CoClass);
+ return meta_import.CreateType (((CoClassAttribute) attr[0]).CoClass);
}
public string GetAttributeDefaultMember ()
return cattrs.AttributeUsage;
}
- public MemberCache LoadMembers (TypeSpec declaringType)
+ public void LoadMembers (TypeSpec declaringType, bool onlyTypes, ref MemberCache cache)
{
+ //
+ // Not interested in members of nested private types unless the importer needs them
+ //
+ if (declaringType.IsPrivate && meta_import.IgnorePrivateMembers) {
+ cache = MemberCache.Empty;
+ return;
+ }
+
var loading_type = (Type) provider;
const BindingFlags all_members = BindingFlags.DeclaredOnly |
BindingFlags.Static | BindingFlags.Instance |
MethodAttributes.Final;
Dictionary<MethodBase, MethodSpec> possible_accessors = null;
+ List<EventSpec> imported_events = null;
+ EventSpec event_spec;
MemberSpec imported;
MethodInfo m;
-
- //
- // This requires methods to be returned first which seems to work for both Mono and .NET
- //
MemberInfo[] all;
try {
all = loading_type.GetMembers (all_members);
declaringType.GetSignatureForError (), declaringType.Assembly.Location);
}
- var cache = new MemberCache (all.Length);
- foreach (var member in all) {
- switch (member.MemberType) {
- case MemberTypes.Constructor:
- case MemberTypes.Method:
- MethodBase mb = (MethodBase) member;
+ if (cache == null) {
+ cache = new MemberCache (all.Length);
- // Ignore explicitly implemented members
- if ((mb.Attributes & explicit_impl) == explicit_impl && (mb.Attributes & MethodAttributes.MemberAccessMask) == MethodAttributes.Private)
+ //
+ // Do the types first as they can be referenced by the members before
+ // they are found or inflated
+ //
+ foreach (var member in all) {
+ if (member.MemberType != MemberTypes.NestedType)
continue;
- // Ignore compiler generated methods
- if (mb.IsPrivate && mb.IsDefined (typeof (CompilerGeneratedAttribute), false))
- continue;
+ Type t = (Type) member;
- imported = Import.CreateMethod (mb, declaringType);
- if (imported.Kind == MemberKind.Method && !imported.IsGeneric) {
- if (possible_accessors == null)
- possible_accessors = new Dictionary<MethodBase, MethodSpec> (ReferenceEquality<MethodBase>.Default);
+ // Ignore compiler generated types, mostly lambda containers
+ if (t.IsNotPublic && t.IsDefined (typeof (CompilerGeneratedAttribute), false))
+ continue;
- // There are no metadata rules for accessors, we have to consider any method as possible candidate
- possible_accessors.Add (mb, (MethodSpec) imported);
- }
+ imported = meta_import.CreateType (t, declaringType, t, 0, false);
+ cache.AddMember (imported);
+ }
- break;
- case MemberTypes.Property:
- if (possible_accessors == null)
+ foreach (var member in all) {
+ if (member.MemberType != MemberTypes.NestedType)
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;
+ meta_import.ImportTypeBase ((Type) member);
+ }
+ }
- m = p.GetSetMethod (true);
- if (m == null || !possible_accessors.TryGetValue (m, out set))
- set = null;
+ if (!onlyTypes) {
+ //
+ // The logic here requires methods to be returned first which seems to work for both Mono and .NET
+ //
+ foreach (var member in all) {
+ switch (member.MemberType) {
+ case MemberTypes.Constructor:
+ case MemberTypes.Method:
+ MethodBase mb = (MethodBase) member;
+ var attrs = mb.Attributes;
+
+ if ((attrs & MethodAttributes.MemberAccessMask) == MethodAttributes.Private) {
+ if (meta_import.IgnorePrivateMembers)
+ continue;
+
+ // Ignore explicitly implemented members
+ if ((attrs & explicit_impl) == explicit_impl)
+ continue;
+
+ // Ignore compiler generated methods
+ if (mb.IsDefined (typeof (CompilerGeneratedAttribute), false))
+ continue;
+ }
- // No accessors registered (e.g. explicit implementation)
- if (get == null && set == null)
- continue;
+ imported = meta_import.CreateMethod (mb, declaringType);
+ if (imported.Kind == MemberKind.Method && !imported.IsGeneric) {
+ if (possible_accessors == null)
+ possible_accessors = new Dictionary<MethodBase, MethodSpec> (ReferenceEquality<MethodBase>.Default);
- imported = Import.CreateProperty (p, declaringType, get, set);
- if (imported == null)
- continue;
+ // There are no metadata rules for accessors, we have to consider any method as possible candidate
+ possible_accessors.Add (mb, (MethodSpec) imported);
+ }
- break;
- case MemberTypes.Event:
- if (possible_accessors == null)
- continue;
+ break;
+ case MemberTypes.Property:
+ 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;
+ 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 = e.GetRemoveMethod (true);
- if (m == null || !possible_accessors.TryGetValue (m, out remove))
- remove = null;
+ m = p.GetSetMethod (true);
+ if (m == null || !possible_accessors.TryGetValue (m, out set))
+ set = null;
- // Both accessors are required
- if (add == null || remove == null)
- continue;
+ // No accessors registered (e.g. explicit implementation)
+ if (get == null && set == null)
+ continue;
- imported = Import.CreateEvent (e, declaringType, add, remove);
- break;
- case MemberTypes.Field:
- var fi = (FieldInfo) member;
+ imported = meta_import.CreateProperty (p, declaringType, get, set);
+ if (imported == null)
+ continue;
- // Ignore compiler generated fields
- if (fi.IsPrivate && fi.IsDefined (typeof (CompilerGeneratedAttribute), false))
- continue;
+ break;
+ case MemberTypes.Event:
+ if (possible_accessors == null)
+ continue;
- imported = Import.CreateField (fi, declaringType);
- if (imported == 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;
- break;
- case MemberTypes.NestedType:
- Type t = (Type) member;
+ m = e.GetRemoveMethod (true);
+ if (m == null || !possible_accessors.TryGetValue (m, out remove))
+ remove = null;
- // Ignore compiler generated types, mostly lambda containers
- if (t.IsNotPublic && t.IsDefined (typeof (CompilerGeneratedAttribute), false))
+ // Both accessors are required
+ if (add == null || remove == null)
+ continue;
+
+ event_spec = meta_import.CreateEvent (e, declaringType, add, remove);
+ if (!meta_import.IgnorePrivateMembers) {
+ if (imported_events == null)
+ imported_events = new List<EventSpec> ();
+
+ imported_events.Add (event_spec);
+ }
+
+ imported = event_spec;
+ break;
+ case MemberTypes.Field:
+ var fi = (FieldInfo) member;
+
+ imported = meta_import.CreateField (fi, declaringType);
+ if (imported == null)
+ continue;
+
+ //
+ // For dynamic binder event has to be fully restored to allow operations
+ // within the type container to work correctly
+ //
+ if (imported_events != null) {
+ // The backing event field should be private but it may not
+ int index = imported_events.FindIndex (l => l.Name == fi.Name);
+ if (index >= 0) {
+ event_spec = imported_events[index];
+ event_spec.BackingField = (FieldSpec) imported;
+ imported_events.RemoveAt (index);
+ continue;
+ }
+ }
+
+ break;
+ case MemberTypes.NestedType:
+ // Already in the cache from the first pass
continue;
+ default:
+ throw new NotImplementedException (member.ToString ());
+ }
- imported = Import.CreateType (t, declaringType);
- break;
- default:
- throw new NotImplementedException (member.ToString ());
+ cache.AddMember (imported);
}
-
- cache.AddMember (imported);
}
if (declaringType.IsInterface && declaringType.Interfaces != null) {
cache.AddInterface (iface);
}
}
-
- return cache;
}
}
throw new NotSupportedException ();
}
- public MemberCache LoadMembers (TypeSpec declaringType)
+ public void LoadMembers (TypeSpec declaringType, bool onlyTypes, ref MemberCache cache)
{
throw new NotImplementedException ();
}