动态语言在Silverlight和JVM中的应用
1. Silverlight中DLR的应用
在Silverlight应用中,当运行相关程序时,浏览器会显示一个带有
>>>
控制台提示符的文本框。以下是一段处理用户输入的代码:
if (e.Key == Key.Enter)
{
int index = helloConsole.Text.LastIndexOf(">>>");
String code = helloConsole.Text.Substring(index + 3);
String result = scriptEngine.Execute(code);
helloConsole.Text += result + "\n>>>";
helloConsole.SelectionStart = helloConsole.Text.Length;
}
当用户输入一些字符并按下回车键时,输入的代码会被评估。
若要在Silverlight应用中使用自定义的Hello语言,需要创建以下文件:
-
dlr.xap
-
Microsoft.Scripting.slvx
-
HelloLanguage.slvx
- 测试HTML页面
创建
dlr.xap
的步骤如下:
1. 复制
C:\ProDLR\src\Examples\Chapter11\dlr
中除
Microsoft.Scripting.slvx
、
IronPython.slvx
和
IronRuby.slvx
之外的所有文件到
C:\ProDLR\src\Examples\Chapter11\hellodlr
。
2. 将
C:\ProDLR\src\Examples\Chapter11\hellodlr
中的
dlr.xap
重命名为
dlr.zip
。
3. 打开
dlr.zip
中的
AppManifest.xaml
,将其内容替换为:
<Deployment xmlns="http://schemas.microsoft.com/client/2007/deployment"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
RuntimeVersion="4.0.50826.0"
EntryPointAssembly="Microsoft.Scripting.Silverlight"
EntryPointType="Microsoft.Scripting.Silverlight.DynamicApplication"
ExternalCallersFromCrossDomain="ScriptableOnly">
<Deployment.Parts>
</Deployment.Parts>
<Deployment.ExternalParts>
<ExtensionPart Source="Microsoft.Scripting.slvx" />
</Deployment.ExternalParts>
</Deployment>
-
打开
languages.config,将其内容替换为:
<Languages>
<Language
names="Hello"
languageContext="HelloLanguage.HelloContext"
extensions=".hello"
assemblies="HelloLanguage.dll"
external="HelloLanguage.slvx"
/>
</Languages>
创建
HelloLanguage.slvx
的步骤如下:
1. 若未构建Chapter11 Visual Studio解决方案,则先进行构建。
2. 将
C:\ProDLR\src\Examples\Chapter11\HelloConsole\HelloLanguage\Bin\Debug
中的
HelloLanguage.dll
压缩为
HelloLanguage.slvx
,并放置在
C:\ProDLR\src\Examples\Chapter11\hellodlr
中。
创建
Microsoft.Scripting.slvx
的步骤如下:
将
C:\ProDLR\lib\SilverlightDLR\debug
中的
Microsoft.Scripting.dll
、
Microsoft.Scripting.Silverlight.dll
和
Microsoft.Dynamic.dll
压缩为
Microsoft.Scripting.slvx
,并放置在
C:\ProDLR\src\Examples\Chapter11\hellodlr
中。
测试Silverlight应用时,打开Web浏览器,导航到
http://prodlr/HelloConsole.htm
。以下是
HelloConsole.htm
的代码:
<html>
<head>
<script type="text/javascript">
window.DLR = {}
DLR.path = "/hellodlr"
DLR.settings = {console: true}
</script>
<script src="/hellodlr/dlr.js" type="text/javascript"></script>
</head>
<body>
<script type="text/Hello">
dummy code
</script>
</body>
</html>
2. 动态语言在JVM中的应用
在Java世界中,有与DLR等效的框架,它能促进动态语言代码在Java虚拟机上运行,支持在Java程序中托管动态语言,并提供语言互操作性。以下是.NET和Java平台在动态语言支持方面的快速比较:
|.NET | Java |
| ---- | ---- |
| IronPython是运行在.NET CLR上的Python语言实现 | Jython是运行在JVM上的Python语言实现 |
| IronRuby是运行在.NET CLR上的Ruby语言实现 | JRuby是运行在JVM上的Ruby语言实现 |
| DLR Hosting API | Java Specification Request (JSR) 223 Scripting for the Java Platform |
| DLR binders, dynamic objects | JSR 292: Supporting Dynamically Typed Languages on the Java Platform |
DLR Hosting API和JSR 223的比较如下:
| DLR Hosting API | JSR 223 Scripting for the Java Platform |
| ---- | ---- |
| ScriptRuntime class | ScriptEngineManager class |
| ScriptEngine class | ScriptEngine class |
| App.config用于发现可用脚本引擎 | META-INF/services/javax.script.ScriptEngineFactory用于发现可用脚本引擎 |
| ScriptScope class | ScriptContext class |
| CompiledCode class | CompiledScript class |
| ScriptSource class | 无等效类 |
| 支持在Silverlight应用中运行动态语言代码 | 支持在Servlet容器中托管动态语言代码 |
若要在Java程序中运行相关代码,需要安装以下软件组件:
- JDK 6或更高版本
- Eclipse IDE
- Jython(版本2.5.1)
- JRuby(版本1.5.1)
3. 在Java程序中托管Python代码
Jython是运行在JVM上的Python语言实现,类似于IronPython运行在CLR上。以下是一个使用JSR 223 API在Java程序中托管Python代码的示例:
private static void printProductNameInPython()
throws ScriptException, NoSuchMethodException, IOException {
ScriptEngineManager manager = new ScriptEngineManager();
ScriptEngine engine = manager.getEngineByName("jython");
Product handClapper = new Product("Hand Clapper", 6);
engine.put("handClapper", handClapper);
engine.eval("print handClapper.getName()");
}
public class Product {
private String name;
private int price;
public Product(String name, int price) {
this.name = name;
this.price = price;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getPrice() {
return price;
}
public void setPrice(int price) {
this.price = price;
}
}
另一个示例是将Python代码作为可调用函数在Java程序中使用:
private static void printProductNameByInvokingPythonFunction()
throws ScriptException, NoSuchMethodException, IOException {
ScriptEngineManager manager = new ScriptEngineManager();
ScriptEngine engine = manager.getEngineByName("jython");
Product handClapper = new Product("Hand Clapper", 6);
engine.eval(new FileReader(new File("src/main/resources/printProductName.py")));
((Invocable) engine).invokeFunction("printProductName", handClapper);
}
printProductName.py
文件内容如下:
def printProductName(x):
print x.getName()
4. 在Java程序中托管Ruby代码
以下是一个使用Ruby代码计算两个产品总价的示例:
private static void calculateProductTotalInRuby() throws ScriptException,
NoSuchMethodException, IOException {
ScriptEngineManager manager = new ScriptEngineManager();
ScriptEngine engine = manager.getEngineByExtension("rb");
Product handClapper = new Product("Hand Clapper", 6);
// 此处代码未完整给出,应继续创建另一个Product实例并调用Ruby函数
}
calculateTotal.rb
文件内容如下:
def calculateTotal(x, y)
return x.getPrice() + y.getPrice()
end
综上所述,无论是在Silverlight应用中使用自定义语言,还是在Java程序中托管Python和Ruby代码,都有相应的方法和工具来实现。通过对比.NET和Java平台在动态语言支持方面的差异,可以更好地选择适合的技术方案。
动态语言在Silverlight和JVM中的应用(续)
5. 运行环境搭建与代码执行流程
为了更清晰地展示在Java程序中运行Python和Ruby代码的流程,我们可以用mermaid流程图来表示:
graph LR
A[安装软件组件] --> B[创建Java项目]
B --> C[配置JSR 223相关依赖]
C --> D[编写Java代码]
D --> E[编写Python或Ruby代码文件]
E --> F[在Java代码中调用Python或Ruby代码]
F --> G[执行Java程序]
具体步骤如下:
1.
安装软件组件
:
- 安装JDK 6或更高版本,例如使用JDK 1.6.0 update 14。
- 安装Eclipse IDE,如版本3.6。
- 下载并安装Jython 2.5.1,将
C:\jython2.5.1\jython.jar
复制到
C:\ProDLR\src\Examples\Chapter12\JavaScripting\lib\Jython
。
- 下载并安装JRuby 1.5.1,将
C:\jruby-1.5.1\lib\jruby.jar
复制到
C:\ProDLR\src\Examples\Chapter12\JavaScripting\lib\JRuby\1.5.1
。
2.
创建Java项目
:在Eclipse IDE中创建一个新的Java项目。
3.
配置JSR 223相关依赖
:将
jython.jar
和
jruby.jar
添加到项目的类路径中,因为它们已经包含了实现JSR 223 API的脚本引擎。
4.
编写Java代码
:根据前面的示例,编写调用Python或Ruby代码的Java代码,如
printProductNameInPython
、
printProductNameByInvokingPythonFunction
和
calculateProductTotalInRuby
等方法。
5.
编写Python或Ruby代码文件
:创建相应的
.py
或
.rb
文件,如
printProductName.py
和
calculateTotal.rb
,并编写具体的函数代码。
6.
在Java代码中调用Python或Ruby代码
:通过
ScriptEngineManager
获取相应的
ScriptEngine
,并使用
eval
或
invokeFunction
等方法调用Python或Ruby代码。
7.
执行Java程序
:运行Java程序,观察输出结果。
6. 技术细节分析
在使用JSR 223 API调用Python和Ruby代码时,有一些技术细节需要注意:
-
获取脚本引擎
:
- 对于Python代码,使用
manager.getEngineByName("jython")
获取Jython脚本引擎。
- 对于Ruby代码,使用
manager.getEngineByExtension("rb")
获取JRuby脚本引擎。
-
变量绑定
:
- 在Java代码中,使用
engine.put
方法将Java对象绑定到脚本引擎的变量中,如
engine.put("handClapper", handClapper)
。
- 在Python或Ruby代码中,可以通过绑定的名称来访问这些对象。
-
函数调用
:
- 对于Python代码,调用文件中的函数时,需要将
ScriptEngine
转换为
Invocable
类型,然后使用
invokeFunction
方法调用函数,如
((Invocable) engine).invokeFunction("printProductName", handClapper)
。
- 与DLR Hosting API相比,JSR 223 API调用Python函数的语法不够直观,需要通过函数名来调用。
7. 语言互操作性优势
动态语言在JVM上的实现,如Jython和JRuby,提供了强大的语言互操作性。通过这种互操作性,我们可以充分利用Java丰富的类库资源,同时结合Python或Ruby灵活的脚本编程能力。例如,在Java程序中使用Python代码处理数据,或者在Python代码中调用Java类的方法。这种结合可以提高开发效率,减少代码量,并且可以根据不同的需求选择最合适的语言来完成特定的任务。
8. 总结与展望
通过以上的介绍,我们了解了在Silverlight应用中使用自定义语言以及在Java程序中托管Python和Ruby代码的方法。在Silverlight方面,通过创建特定的文件和配置,可以实现自定义语言的支持。在Java方面,JSR 223 API为我们提供了一种方便的方式来在Java程序中运行动态语言代码。
未来,随着动态语言和虚拟机技术的不断发展,我们可以期待更高效、更便捷的语言互操作性解决方案。例如,可能会出现更简洁的API,使得在Java程序中调用Python和Ruby代码更加自然和直观。同时,动态语言在不同平台上的性能也可能会得到进一步提升,为开发者提供更好的开发体验。
总之,掌握动态语言在Silverlight和JVM中的应用,对于开发者来说是一项非常有价值的技能,可以帮助我们在不同的场景中选择最合适的技术方案,提高开发效率和代码质量。
超级会员免费看
5

被折叠的 条评论
为什么被折叠?



