初试IronPython与.NET的集成

在得知IronPython如今已步入1.0 RC1后兴奋不已,赶快下载下来试用。虽说功能性变化不多(加入了试用性Python 2.5的语法支持:D),但稳定性如今已提高了不少,应该说可以用来投入正式使用了。:)

如何用好IronPython

翻看了一下Tutorials,发现和以前的内容差不多,按照Tutorials中的方法尝试了一下在C#中嵌入IronPython 代码,发现还很不错,最起码可行,虽然速度肯定没有用C#直接写出来的快(因为IronPython需要动态编译的缘故)。

好的,现在我们拥有了一项较稳定的可以投入使用的新技术了,但是如果没有市场,那么这个新技术是不能够生存的,所以我左思右想 IronPython在企业级开发中到底占了什么地位(因为我是做企业级开发的:)),有何等优势呢?通过分析现有IronPython的特征,我得到了一个结论,那就是它比较适合做脚本引擎或者简单的客户端。以下是我分析的IronPython的一些特征:

  1. Python的语法,灵活性相当的高!
  2. 与.NET Framework的交互实现的非常的好,现在用Python的语法也可以用.NET的类库了。
  3. 在其他.NET语言中可以通过引用IronPython.dll来执行IronPython文件并且可以实现内存共享(在同一AppDomain中)。
  4. 纯IronPython程序启动非常慢。
  5. 由于IronPython的特殊性,它所编译出来的程序集中的成员并非你所想象的,所以不能够由其他程序集直接引用使用。这主要还是因为Python是一种动态类型语言,所以无法在编译时给予合适的静态类型(唯一合适的就是System.Object)。另外为了与CPython保持兼容性,IronPython也是以module为单位进行group的,也就是一个module被编译成一个类,这个module中的所有成员,包括class都被当作成员编译在这个类中。

基于以上一些IronPython现有的特征来看,我觉得它更适合使用.NET 程序集,而非为.NET程序提供功能(虽然也是可行的,也是我希望的),所以我建议将IronPython用作客户端以及脚本引擎一类的用途上,因为这类程序是属于consumer类的,它们使用现成的API,但是它们不为其他人提供新的API。

如何用IronPython为.NET程序提供API

读者可能会说我自相矛盾,刚刚才说过IronPython不适合用来提供API,怎么现在又提起这件事来了呢(唉,人本身就是一种很矛盾的生物)?!其实就像上面我在括号中提及的,利用IronPython的交互能力与语言的灵活性为我的.NET程序提供简化的解决方案是我的期望,虽然速度方面还不尽人意,但优化的空间永远都是存在的,我相信随着时间的推移IronPython会在性能方面做的更出色(从这方面来看我是个乐观主义者:D)。

为了简化主程序与IronPython文件的交互与维护难度,我决定将IronPython文件作为服务(service)来看待,IronPython所提供的每一个API就是一个独立的服务,每次需要使用这个服务的时候我只需向它发送相应的消息(message)即可,而它,会返回给我一个回应(response)如果有必要的话。我觉得这样做比较符合目前的SOA潮流。(如果你还不知道SOA是什么的话,一句话告诉你,它是一种企业级集成手段)

我的做法很简单,只是初步实现了一个对IronPython文件调用的封装,示例如下。

None.gif  List < int >  a  =   new  List < int > ();
None.gif a.Add(
1 );
None.gif a.Add(
2 );
None.gif a.Add(
3 );
None.gif
None.gif List
< int >  b  =   new  List < int > ();
None.gif b.Add(
4 );
None.gif b.Add(
5 );
None.gif b.Add(
6 );
None.gif
None.gif PyFacade
< IList < IList < object >>>  py  =
None.gif    
new  PyFacade < IList < IList < object >>> ();
None.gif py.PythonFile 
=   " mayorThenTen.py " ;
None.gif py.Arguments.Add(
" listA " , a);
None.gif py.Arguments.Add(
" listB " , b);
None.gif py.Execute();
None.gif
ExpandedBlockStart.gifContractedBlock.gif 
foreach  (IList < object >  tuple  in  py.Result)  dot.gif {
InBlock.gif    Console.Write(tuple[
0]);
InBlock.gif    Console.Write(
"");
InBlock.gif    Console.Write(tuple[
1]);
InBlock.gif    Console.WriteLine();
ExpandedBlockEnd.gif }

PyFacade的代码如下。

None.gif using  System;
None.gif
using  System.Collections.Generic;
None.gif
None.gif
using  IronPython.Hosting;
None.gif
ExpandedBlockStart.gifContractedBlock.gif
namespace  Cavingdeep.Python  dot.gif {
ExpandedSubBlockStart.gifContractedSubBlock.gif   
public class PyFacade<T> dot.gif{
InBlock.gif      
public const string ResultVariableName = "_result_";
InBlock.gif
InBlock.gif      
private PythonEngine engine = new PythonEngine();
InBlock.gif
InBlock.gif      
private string pythonFile;
InBlock.gif      
private Result<T> result = new Result<T>();
InBlock.gif      
private IDictionary<string,object> args =
InBlock.gif         
new Dictionary<string,object>();
InBlock.gif
ExpandedSubBlockStart.gifContractedSubBlock.gif      
public string PythonFile dot.gif{
ExpandedSubBlockStart.gifContractedSubBlock.gif         
get dot.gif{return this.pythonFile;}
ExpandedSubBlockStart.gifContractedSubBlock.gif         
set dot.gif{this.pythonFile = value;}
ExpandedSubBlockEnd.gif      }

InBlock.gif
ExpandedSubBlockStart.gifContractedSubBlock.gif      
public T Result dot.gif{
ExpandedSubBlockStart.gifContractedSubBlock.gif         
get dot.gif{return this.result.Value;}
ExpandedSubBlockEnd.gif      }

InBlock.gif
ExpandedSubBlockStart.gifContractedSubBlock.gif      
public IDictionary<string,object> Arguments dot.gif{
ExpandedSubBlockStart.gifContractedSubBlock.gif         
get dot.gif{return this.args;}
ExpandedSubBlockEnd.gif      }

InBlock.gif
ExpandedSubBlockStart.gifContractedSubBlock.gif      
public void Execute() dot.gif{
InBlock.gif         engine.Globals[ResultVariableName] 
= this.result;
InBlock.gif
ExpandedSubBlockStart.gifContractedSubBlock.gif         
foreach (KeyValuePair<string,object> arg in this.args) dot.gif{
InBlock.gif            engine.Globals[arg.Key] 
= arg.Value;
ExpandedSubBlockEnd.gif         }

InBlock.gif
InBlock.gif         engine.ExecuteFile(
this.pythonFile);
ExpandedSubBlockEnd.gif      }

ExpandedSubBlockEnd.gif   }

ExpandedBlockEnd.gif}

None.gif

Result的代码如下。

None.gif using  System;
None.gif
ExpandedBlockStart.gifContractedBlock.gif
namespace  Cavingdeep.Python  dot.gif {
ExpandedSubBlockStart.gifContractedSubBlock.gif   
public class Result<T> dot.gif{
InBlock.gif      
public T Value;
ExpandedSubBlockEnd.gif   }

ExpandedBlockEnd.gif}

None.gif

mayorThenTen.py的代码如下,这是这个示例中用到的IronPython文件。

None.gif def  mayorThenTen(a, b):
None.gif   
return  [(x, y)  for  x  in  a  for  y  in  b  if  x  +  y  >   5 ]
None.gif
None.gif
if  globals().has_key( ' _result_ ' ):
None.gif   _result_.Value 
=  mayorThenTen(listA, listB)
None.gif

这里的这个PyFacade是个比较通用的与IronPython交互的接口类,在真正的应用中建议用强类型模式(强类型设计实践)加以封装以得到type safety等好处。

关于PyFacade是如何与IronPython文件交互一题,简单地说就是通过那个_result_变量,它会在IronPython文件中被赋值,这个值是外界可见的,也就是说IronPython文件的执行与当前程序是在一个AppDomain中的。有关这类知识感兴趣的读者可以去研究一下动态编译、加载与程序域(AppDomain)等知识。

转载于:https://www.cnblogs.com/cavingdeep/archive/2006/08/01/464781.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值