Hosting the DLR in Silverlight

Hosting a dynamic language in Silverlight gives any Silverlight application (in any Silverlight language: C#/VB/Ruby/Python/JScript/others) the ability to run code in either Python, Ruby, JScript, or any other DLR-based language, from inside itself. For more information on the DLR and hosting, see http://dlr.codeplex.com/Wiki/View.aspx?titleDocs%20and%20specs&referringTitleHome

Differences between desktop and Silverlight

The code necessary to host the DLR inside of Silverlight is different than on the desktop. Also, the code different between static and dynamic languages. In both cases, they only differ in how you construct the ScriptRuntimeSetup object.

Discovering languages

The first difference is how ScriptRuntimeSetup finds out the available languages. This information can either be loaded from a configuration file inside the XAP (language.config), or from the already-loaded assemblies themselves. The desktop does not allow loading from the assemblies, since it doesn't want to encourage loading all the language assemblies when they are not needed. However, Silverlight pre-loads all assemblies anyway, so both options are given in Silverlight.

Microsoft.Scripting.Silverlight.Configuration has helper methods to load the configuration from either a language.config from the XAP file, or, to avoid having the config file, the language assemblies themselves.

Platform Adaptation Layer

The desktop and Silverlight differ in a big way when it comes to the File system; Silverlight does not have access to the machine's file system. Instead, it can only access files inside the XAP file, or in Isolated Storage. The DLR abstracts platform functionality into a PlatformAdaptationLayer (PAL), which can be changed by supplying a custom ScriptHost, which knows about a custom PAL.

The DLR's default PAL doesn't define any behavior for Silverlight; it just throws "NotImplementedException" if any platform functionality is used. Microsoft.Scripting.Silverlight.BrowserScriptHost is a custom ScriptHost which knows about an internal BrowserPAL class, which directs any read-only file system access to the XAP.

Hosting the DLR from C# or VB

The following tells the ScriptRuntimeSetup about the avaliable languages from the loaded assemblies, and sets the HostType to BrowserScriptHost, which will make read-only platform-specific features work. It also pre-references platform assemblies so AddReference/LoadAssembly doesn't need to be called from script code.

C#

using Microsoft.Scripting.Hosting;
using Microsoft.Scripting.Silverlight;

ScriptRuntimeSetup setup = Configuration.LoadFromAssemblies(Package.GetManifestAssemblies());
setup.HostType = typeof(BrowserScriptHost);
ScriptRuntime runtime = new ScriptRuntime(setup);
// load platform assemblies so you don't need to call LoadAssembly in script code.
foreach (string name in new string[] { "mscorlib", "System", "System.Windows", "System.Windows.Browser", "System.Net" })
{
    runtime.LoadAssembly(runtime.Host.PlatformAdaptationLayer.LoadAssembly(name));
}

// now the desktop and Silverlight are the same ...
ScriptEngine engine = runtime.GetEngine("Python")
ScriptSource source = engine.CreateScriptSourceFromString("System.Windows.Browser.HtmlPage.Document.Message.innerHTML = 'Hello, World'")
source.Compile().Execute();

Hosting the DLR from Python, Ruby, or JScript

Since the DLR/Silverlight integration is a C# application and hosts the DLR itself, the above work is already done for a dynamic language. Therefore, dynamic languages only need access to the ScriptRuntime or ScriptRuntimeSetup objects.

Ruby

require 'Microsoft.Scripting'
include Microsoft.Scripting.Silverlight
include Microsoft.Scripting.Hosting
runtime = ScriptRuntime.new(DynamicApplication.current.runtime.setup)

# or, is you just want to reuse the ScriptRuntime object:
runtime = DynamicApplication.current.runtime

Python

import clr
clr.AddReference("Microsoft.Scripting")
from Microsoft.Scripting.Hosting import ScriptRuntime, ScriptRuntimeSetup
from Microsoft.Scripting.Silverlight import DynamicApplication
runtime = ScriptRuntime(DynamicApplication.Current.Runtime.Setup

# or, is you just want to reuse the ScriptRuntime object:
runtime = DynamicApplication.Current.Runtime

Last edited May 15, 2009 at 7:06 PM by jimmysch, version 10

Comments

No comments yet.