public Type TryGetType(string name) { if (ImportedTypes.ContainsKey(name)) { return(ImportedTypes[name]); } // If the type name does not exist in the local or built-in variables, then it is out of scope string lookupScr = String.Format("clr.GetClrType({0}) if (\"{0}\" in locals() or \"{0}\" in __builtins__) and isinstance({0}, type) else None", name); dynamic type = null; try { type = engine.CreateScriptSourceFromString(lookupScr, SourceCodeKind.Expression).Execute(scope); } catch (Exception e) { Log(String.Format("Failed to look up type: {0}", name)); Log(e.ToString()); } var foundType = type as Type; if (foundType != null) { ImportedTypes[name] = foundType; } return(foundType); }
/// <summary> /// Find all import statements and import into scope. If the type is already in the scope, this will be skipped. /// </summary> /// <param name="code">The code to discover the import statements.</param> public void UpdateImportedTypes(string code) { // Detect all lib references prior to attempting to import anything var refs = FindClrReferences(code); foreach (var statement in refs) { var previousTries = 0; badStatements.TryGetValue(statement, out previousTries); // TODO - Why is this 3? Should this be a constant? Is it related to knownAssembies.Length? if (previousTries > 3) { continue; } try { string libName = MATCH_FIRST_QUOTED_NAME.Match(statement).Groups[1].Value; // If the library name cannot be found in the loaded clr modules if (!clrModules.Contains(libName)) { if (statement.Contains("AddReferenceToFileAndPath")) { engine.CreateScriptSourceFromString(statement, SourceCodeKind.SingleStatement).Execute(scope); clrModules.Add(libName); continue; } if (AppDomain.CurrentDomain.GetAssemblies().Any(x => x.GetName().Name == libName)) { engine.CreateScriptSourceFromString(statement, SourceCodeKind.SingleStatement).Execute(scope); clrModules.Add(libName); } } } catch (Exception e) { Log(String.Format("Failed to reference library: {0}", statement)); Log(e.ToString()); badStatements[statement] = previousTries + 1; } } var importStatements = FindAllImportStatements(code); // Format import statements based on available data foreach (var i in importStatements) { string module = i.Item1; string memberName = i.Item2; string asname = i.Item3; string name = asname ?? memberName; string statement = ""; var previousTries = 0; if (name != "*" && (scope.ContainsVariable(name) || ImportedTypes.ContainsKey(name))) { continue; } try { if (module == null) { if (asname == null) { statement = String.Format("import {0}", memberName); } else { statement = String.Format("import {0} as {1}", memberName, asname); } } else { if (memberName != "*" && asname != null) { statement = String.Format("from {0} import {1} as {2}", module, memberName, asname); } else { statement = String.Format("from {0} import *", module); } } badStatements.TryGetValue(statement, out previousTries); if (previousTries > 3) { continue; } engine.CreateScriptSourceFromString(statement, SourceCodeKind.SingleStatement).Execute(scope); if (memberName == "*") { continue; } string typeName = module == null ? memberName : String.Format("{0}.{1}", module, memberName); var type = Type.GetType(typeName); ImportedTypes.Add(name, type); } catch (Exception) { Log(String.Format("Failed to load module: {0}, with statement: {1}", memberName, statement)); // Log(e.ToString()); badStatements[statement] = previousTries + 1; } } }