/// <summary> /// Scans an assembly for exported namespaces, adding them to the /// mapping of valid namespaces. Note that for a given namespace /// a.b.c.d, each of a, a.b, a.b.c and a.b.c.d are considered to /// be valid namespaces (to better match Python import semantics). /// </summary> internal static void ScanAssembly(Assembly assembly) { if (assembly.GetCustomAttribute <PyExportAttribute>()?.Export == false) { return; } // A couple of things we want to do here: first, we want to // gather a list of all of the namespaces contributed to by // the assembly. foreach (Type t in GetTypes(assembly)) { string ns = t.Namespace ?? ""; if (!namespaces.ContainsKey(ns)) { string[] names = ns.Split('.'); var s = ""; for (var n = 0; n < names.Length; n++) { s = n == 0 ? names[0] : s + "." + names[n]; if (namespaces.TryAdd(s, new ConcurrentDictionary <Assembly, string>())) { ImportHook.AddNamespace(s); } } } if (ns != null) { namespaces[ns].TryAdd(assembly, string.Empty); } if (ns != null && t.IsGenericTypeDefinition) { GenericUtil.Register(t); } } }
public static Assembly AddReference(string name) { AssemblyManager.UpdatePath(); var origNs = AssemblyManager.GetNamespaces(); Assembly assembly = null; assembly = AssemblyManager.FindLoadedAssembly(name); if (assembly == null) { assembly = AssemblyManager.LoadAssemblyPath(name); } if (assembly == null) { assembly = AssemblyManager.LoadAssembly(name); } if (assembly == null) { assembly = AssemblyManager.LoadAssemblyFullPath(name); } if (assembly == null) { throw new FileNotFoundException($"Unable to find assembly '{name}'."); } // Classes that are not in a namespace needs an extra nudge to be found. ImportHook.UpdateCLRModuleDict(); // A bit heavyhanded, but we can't use the AssemblyManager's AssemblyLoadHandler // method because it may be called from other threads, leading to deadlocks // if it is called while Python code is executing. var currNs = AssemblyManager.GetNamespaces().Except(origNs); foreach (var ns in currNs) { ImportHook.AddNamespace(ns); } return(assembly); }