using System.Linq; using System; using System.Collections.Generic; using System.Resources; namespace Python.Runtime { /// /// This class is responsible for efficiently maintaining the bits /// of information we need to support aliases with 'nice names'. /// internal static class GenericUtil { /// /// Maps namespace -> generic base name -> list of generic type names /// private static Dictionary>> mapping; public static void Reset() { mapping = new Dictionary>>(); } /// /// Register a generic type that appears in a given namespace. /// /// A generic type definition (t.IsGenericTypeDefinition must be true) internal static void Register(Type t) { if (null == t.Namespace || null == t.Name) { return; } Dictionary> nsmap; if (!mapping.TryGetValue(t.Namespace, out nsmap)) { nsmap = new Dictionary>(); mapping[t.Namespace] = nsmap; } string basename = GetBasename(t.Name); List gnames; if (!nsmap.TryGetValue(basename, out gnames)) { gnames = new List(); nsmap[basename] = gnames; } gnames.Add(t.Name); } /// /// xxx /// public static List GetGenericBaseNames(string ns) { Dictionary> nsmap; if (!mapping.TryGetValue(ns, out nsmap)) { return null; } var names = new List(); foreach (string key in nsmap.Keys) { names.Add(key); } return names; } /// /// Finds a generic type with the given number of generic parameters and the same name and namespace as . /// public static Type GenericForType(Type t, int paramCount) { return GenericByName(t.Namespace, t.Name, paramCount); } /// /// Finds a generic type in the given namespace with the given name and number of generic parameters. /// public static Type GenericByName(string ns, string basename, int paramCount) { Dictionary> nsmap; if (!mapping.TryGetValue(ns, out nsmap)) { return null; } List names; if (!nsmap.TryGetValue(GetBasename(basename), out names)) { return null; } foreach (string name in names) { string qname = ns + "." + name; Type o = AssemblyManager.LookupTypes(qname).FirstOrDefault(); if (o != null && o.GetGenericArguments().Length == paramCount) { return o; } } return null; } /// /// xxx /// public static string GenericNameForBaseName(string ns, string name) { Dictionary> nsmap; if (!mapping.TryGetValue(ns, out nsmap)) { return null; } List gnames; nsmap.TryGetValue(name, out gnames); if (gnames?.Count > 0) { return gnames[0]; } return null; } private static string GetBasename(string name) { int tick = name.IndexOf("`"); if (tick > -1) { return name.Substring(0, tick); } else { return name; } } } }