// This is the type_cache from the assemblies to avoid
// hitting System.Reflection on every lookup.
// </summary>
- static Hashtable types;
+ static CaseInsensitiveHashtable types;
// <remarks>
// This is used to hotld the corresponding TypeContainer objects
// since we need this in FindMembers
// </remarks>
- static Hashtable typecontainers;
+ static CaseInsensitiveHashtable typecontainers;
// <remarks>
// Keeps track of those types that are defined by the
modules = null;
user_types = new ArrayList ();
- types = new Hashtable ();
- typecontainers = new Hashtable ();
+ types = new CaseInsensitiveHashtable ();
+ typecontainers = new CaseInsensitiveHashtable ();
builder_to_declspace = new PtrHashtable ();
builder_to_attr = new PtrHashtable ();
modules = n;
}
+ //
+ // Low-level lookup, cache-less
+ //
+ static Type LookupTypeReflection (string name)
+ {
+ Type t;
+
+ foreach (Assembly a in assemblies){
+ t = a.GetType (name);
+ if (t != null)
+ return t;
+ }
+
+ foreach (ModuleBuilder mb in modules) {
+ t = mb.GetType (name);
+ if (t != null){
+ return t;
+ }
+ }
+ return null;
+ }
+
+ //
+ // This function is used when you want to avoid the lookups, and want to go
+ // directly to the source. This will use the cache.
+ //
+ // Notice that bypassing the cache is bad, because on Microsoft.NET runtime
+ // GetType ("DynamicType[]") != GetType ("DynamicType[]"), and there is no
+ // way to test things other than doing a fullname compare
+ //
+ public static Type LookupTypeDirect (string name)
+ {
+ Type t = (Type) types [name];
+ if (t != null)
+ return t;
+
+ t = LookupTypeReflection (name);
+ if (t == null)
+ return null;
+
+ types [name] = t;
+ return t;
+ }
+
/// <summary>
- /// Returns the Type associated with @name
+ /// Returns the Type associated with @name, takes care of the fact that
+ /// reflection expects nested types to be separated from the main type
+ /// with a "+" instead of a "."
/// </summary>
public static Type LookupType (string name)
{
if (t != null)
return t;
- foreach (Assembly a in assemblies){
- t = a.GetType (name);
- if (t != null){
- types [name] = t;
+ //
+ // Optimization: ComposedCast will work with an existing type, and might already have the
+ // full name of the type, so the full system lookup can probably be avoided.
+ //
+
+ string [] elements = name.Split ('.');
+ int count = elements.Length;
- return t;
- }
- }
+ for (int n = 1; n <= count; n++){
+ string top_level_type = String.Join (".", elements, 0, n);
- foreach (ModuleBuilder mb in modules) {
- t = mb.GetType (name);
- if (t != null) {
+ t = (Type) types [top_level_type];
+ if (t == null){
+ t = LookupTypeReflection (top_level_type);
+ if (t == null)
+ continue;
+ }
+
+ if (count == n){
types [name] = t;
return t;
- }
+ }
+
+ string newt = top_level_type + "+" + String.Join ("+", elements, n, count - n);
+ t = LookupTypeDirect (newt);
+ if (t != null)
+ types [newt] = t;
+ return t;
}
-
return null;
}
+ //
+ // Returns a list of all namespaces in the assemblies and types loaded.
+ //
+ public static CaseInsensitiveHashtable GetNamespaces ()
+ {
+ CaseInsensitiveHashtable namespaces = new CaseInsensitiveHashtable ();
+
+ foreach (Assembly a in assemblies){
+ foreach (Type t in a.GetTypes ()){
+ string ns = t.Namespace;
+
+ if (namespaces.Contains (ns))
+ continue;
+ namespaces [ns] = ns;
+ }
+ }
+
+ foreach (ModuleBuilder mb in modules){
+ foreach (Type t in mb.GetTypes ()){
+ string ns = t.Namespace;
+
+ if (namespaces.Contains (ns))
+ continue;
+ namespaces [ns] = ns;
+ }
+ }
+ return namespaces;
+ }
+
/// <summary>
/// Returns the C# name of a type if possible, or the full type name otherwise
/// </summary>
/// <summary>
/// Returns the ConstructorInfo for "args"
/// </summary>
- static ConstructorInfo GetConstructor (Type t, Type [] args)
+ public static ConstructorInfo GetConstructor (Type t, Type [] args)
{
MemberList list;
Signature sig;
const BindingFlags instance_and_static = BindingFlags.Static | BindingFlags.Instance;
- static Hashtable type_hash = new Hashtable ();
+ static CaseInsensitiveHashtable type_hash = new CaseInsensitiveHashtable ();
/// <remarks>
/// This is the "old", non-cache based FindMembers() function. We cannot use
MemberFilter filter, object criteria)
{
DeclSpace decl = (DeclSpace) builder_to_declspace [t];
-
+bf |= BindingFlags.IgnoreCase;
//
// `builder_to_declspace' contains all dynamic types.
//
else
return false;
}
-
+
+ //
+ // Whether a type is unmanaged. This is used by the unsafe code (25.2)
+ //
+ public static bool IsUnmanagedType (Type t)
+ {
+ if (IsBuiltinType (t) && t != TypeManager.string_type)
+ return true;
+
+ if (IsEnumType (t))
+ return true;
+
+ if (t.IsPointer)
+ return true;
+
+ if (IsValueType (t)){
+ if (t is TypeBuilder){
+ TypeContainer tc = LookupTypeContainer (t);
+
+ foreach (Field f in tc.Fields){
+ if (f.FieldBuilder.IsStatic)
+ continue;
+ if (!IsUnmanagedType (f.FieldBuilder.FieldType))
+ return false;
+ }
+ } else {
+ FieldInfo [] fields = t.GetFields ();
+
+ foreach (FieldInfo f in fields){
+ if (f.IsStatic)
+ continue;
+ if (!IsUnmanagedType (f.FieldType))
+ return false;
+ }
+ }
+ return true;
+ }
+
+ return false;
+ }
+
public static bool IsValueType (Type t)
{
if (t.IsSubclassOf (TypeManager.value_type))
return false;
}
+ //
+ // Checks whether `type' is a nested child of `parent'.
+ //
+ public static bool IsNestedChildOf (Type type, Type parent)
+ {
+ if ((type == parent) || type.IsSubclassOf (parent))
+ return false;
+ else
+ return IsSubclassOrNestedChildOf (type, parent);
+ }
+
/// <summary>
/// Returns the User Defined Types
/// </summary>
}
}
- public static Hashtable TypeContainers {
+ public static CaseInsensitiveHashtable TypeContainers {
get {
return typecontainers;
}
// This is a workaround the fact that GetValue is not
// supported for dynamic types
// </remarks>
- static Hashtable fields = new Hashtable ();
+ static CaseInsensitiveHashtable fields = new CaseInsensitiveHashtable ();
static public bool RegisterFieldValue (FieldBuilder fb, object value)
{
if (fields.Contains (fb))
return fields [fb];
}
- static Hashtable fieldbuilders_to_fields = new Hashtable ();
+ static CaseInsensitiveHashtable fieldbuilders_to_fields = new CaseInsensitiveHashtable ();
static public bool RegisterFieldBase (FieldBuilder fb, FieldBase f)
{
if (fieldbuilders_to_fields.Contains (fb))
return (FieldBase) fieldbuilders_to_fields [fb];
}
- static Hashtable events;
+ static CaseInsensitiveHashtable events;
static public bool RegisterEvent (MyEventBuilder eb, MethodBase add, MethodBase remove)
{
if (events == null)
- events = new Hashtable ();
+ events = new CaseInsensitiveHashtable ();
if (events.Contains (eb))
return false;
return ei.GetAddMethod ();
}
- static Hashtable priv_fields_events;
+ static CaseInsensitiveHashtable priv_fields_events;
static public bool RegisterPrivateFieldOfEvent (EventInfo einfo, FieldBuilder builder)
{
if (priv_fields_events == null)
- priv_fields_events = new Hashtable ();
+ priv_fields_events = new CaseInsensitiveHashtable ();
if (priv_fields_events.Contains (einfo))
return false;
return (MemberInfo) priv_fields_events [ei];
}
- static Hashtable properties;
+ static CaseInsensitiveHashtable properties;
static public bool RegisterProperty (PropertyBuilder pb, MethodBase get, MethodBase set)
{
if (properties == null)
- properties = new Hashtable ();
+ properties = new CaseInsensitiveHashtable ();
if (properties.Contains (pb))
return false;
return true;
}
- //
- // FIXME: we need to return the accessors depending on whether
- // they are visible or not.
- //
- static public MethodInfo [] GetAccessors (PropertyInfo pi)
- {
- MethodInfo [] ret;
-
- if (pi is PropertyBuilder){
- Pair pair = (Pair) properties [pi];
-
- ret = new MethodInfo [2];
- ret [0] = (MethodInfo) pair.First;
- ret [1] = (MethodInfo) pair.Second;
-
- return ret;
- } else {
- MethodInfo [] mi = new MethodInfo [2];
-
- //
- // Why this and not pi.GetAccessors?
- // Because sometimes index 0 is the getter
- // sometimes it is 1
- //
- mi [0] = pi.GetGetMethod (true);
- mi [1] = pi.GetSetMethod (true);
-
- return mi;
- }
- }
-
static public MethodInfo GetPropertyGetter (PropertyInfo pi)
{
if (pi is PropertyBuilder){
if (!IsSubclassOrNestedChildOf (closure_invocation_type, mb.DeclaringType))
return false;
- // Although a derived class can access protected members of its base class
- // it cannot do so through an instance of the base class (CS1540).
- if ((closure_invocation_type != closure_start_type) &&
- closure_invocation_type.IsSubclassOf (closure_start_type))
- return false;
-
return true;
}
} else
private_ok = always_ok_flag;
- if (private_ok || invocation_type.IsSubclassOf (current_type))
+ if (invocation_type.IsSubclassOf (current_type))
+ private_ok = true;
+
+ if (private_ok)
bf = original_bf | BindingFlags.NonPublic;
} else {
private_ok = false;
if (list.Count == 0)
continue;
-
+
//
// Events and types are returned by both `static' and `instance'
// searches, which means that our above FindMembers will