using System;
using Microsoft.Scripting;
using Microsoft.Scripting.Hosting;
using Microsoft.Scripting.Runtime;
namespace ScopeOps {
public class ScopeHiererchy {
public static void Main() {
ScriptEngine eng = new ScriptRuntime().GetEngine("py");
ScriptScope baseScope = eng.CreateScope();
var dict = new DynamicLookupDictionary(baseScope);
//set variables in the base scope.
baseScope.SetVariable("base_int", 100);
baseScope.SetVariable("base_string", "from base");
ScriptScope useScope = eng.CreateScope(dict);
var src = eng.CreateScriptSourceFromString(
"print base_int\nprint base_string",
SourceCodeKind.Statements);
//'useScope' doesn't have the variables accessed by the script yet.
//The overriden 'get' method dynamically looks up the variable in the base scope.
src.Execute(useScope);
}
}
internal class DynamicLookupDictionary : CustomSymbolDictionary {
private ScriptScope _baseScope;
public DynamicLookupDictionary(ScriptScope baseScope):base() {
_baseScope = baseScope;
}
//This method would be invoked whenever a script executing in the context of this scope
//accesses a variable
protected override bool TryGetExtraValue(SymbolId key, out object value) {
//If the variable is part of the base scope, return that value - this effectively
//creates a 'scope chain'
if (_baseScope.TryGetVariable(SymbolTable.IdToString(key), out value)) {
return true;
}
value = null;
return false;
}
public override SymbolId[] GetExtraKeys() {
return null;
}
protected override bool TrySetExtraValue(SymbolId key, object value) {
return false;
}
}
}