IronPython中共享的C#基类如何向下转型
在项目中,我们使用IronPython来定义工作流脚本来以应对科研多变的需求。项目使用的主要语言仍然是C#,使用C#封装了各种基础服务与基础设施。Python脚本只使用C#提供的服务,或者说只定义了逻辑流程,一切实际操作都有C#来操刀。一切工作良好,但在工程师(engineer)脚本[1]中,我们需要直接对具体硬件定义逻辑流程。这些流程可以用来测试硬件的可连接性与功能正确性,也可以用来对硬件做压力测试。
按正常思维来说,脚本不应该访问物理硬件的Api。的确,我们在C#中已经提供了良好的抽象硬件接口。但该硬件产品处于研发阶段,硬件部件种类繁多,硬件参数以及实现逻辑上存在多样性。面向工程师,他们更需要直接去面对具体的硬件,去设置硬件参数,去针对具体硬件设计测试逻辑。
我们通过共享变量的方式将C#对象共享给IronPython脚本[2]。IronPython获取到C#对象之后,直接使用C#实例服务。在创建C#硬件对象时,我们使用了IOC服务,最终使用的全部都是顶层的硬件抽象接口。那么当这些基类实例(虽然持有还是子类实例)共享到IronPython脚本时,他们是什么类型?如果要访问具体硬件的差异化方法,那么必须进行向下转型,这在Python中如何实现?
IronPython建立在Python(2.7)之上,Python作为一门脚本语言,本身是没有类型的或者叫鸭子类型。在这种风格中,一个对象有效的语义,不是由继承自特定的类或实现特定的接口,而是由"当前方法和属性的集合"决定。[3] 我们在使用Python对象实例时,并不关心它的类型,更无转型之说。下面是python 2.7中对Class的解释:
Compared with other programming languages,Python’s class mechanism adds classes with a minimum of new syntax and semantics. It is a mixture of the class mechanisms found in C++ and Modula-3.
Python classes provide all the standard features of Object Oriented Programming: the class inheritance mechanism allows multiple base classes, a derived class can override any methods of its
base class or classes, and a method can call the method of a base class with the same name. Objects can contain arbitrary amounts and kinds of data. As is true for modules, classes partake
of the dynamic nature of Python: they are created at runtime, and can be modified further after creation. [4]
从上述的说明可以看出,python(2.7) Class主要用来定义方法与属性集合,即使是继承,也只是实现复用的一种手段。既然Python无类型,那么C#共享给IronPython的对象实例到底是什么类型实例呢?如果共享的是实例的具体类型(new时的类型),那么在IronPython中,操作的逻辑对象其实一直是真实的物理设备对象。
通过简单的测试,我发现真的是这样。测试方法是这样的,在C#中定义了两个类,这两个类为父子关系。通过基类类型共享到IronPython脚本,然后检查共享类型的具体类型,即在Python中检查其支持的操作。
C#代码如下:
class Program
{
private const string Path = @"v0.1\scripting\Py\engineer";
static void Main(string[] args)
{
BaseA obj = new SubB();
obj.Say(); var engine = Python.CreateEngine();
try
{
var scope = engine.CreateScope();
scope.SetVariable("SB", obj);
engine.ExecuteFile($"{Path}\\crame.py",scope); }
catch(Exception ex)
{
WriteLine(ex);
} ReadLine();
}
} public class BaseA
{
public virtual void Say()
{
WriteLine("Base A");
}
} public class SubB : BaseA
{
public override void Say()
{
WriteLine("Sub Class B");
} public void Test()
{
WriteLine("Test method");
}
}
Python脚本如下:
#crame.py
print('SB' in globals())
csb = globals().get('SB')
print(dir(csb))
csb.Test()
csb.Say()
输出如下:
Sub Class B
True
['Equals', 'GetHashCode', 'GetType', 'MemberwiseClone', 'ReferenceEquals', 'Say', 'Test', 'ToString', '__class__', '__de
lattr__', '__doc__', '__format__', '__getattribute__', '__hash__', '__init__', '__new__', '__reduce__', '__reduce_ex__',
'__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__']
Test method
Sub Class B
从上可以看出,传递给IronPython的C#实例为其具体的对象类型,那就不存在在Python中需要向下转型具体型别的问题了。
参考
[1] 这里的工程师脚本面向光学工程师、液路工程师、电路板工程师等
[2] IronPython, http://ironpython.net/
[3] 鸭子类型, https://zh.wikipedia.org/zh-hans/%E9%B8%AD%E5%AD%90%E7%B1%BB%E5%9E%8B
[4] Python Class (2.7), https://docs.python.org/2.7/tutorial/classes.html
IronPython中共享的C#基类如何向下转型的更多相关文章
- 正确理解Widget::Widget(QWidget *parent) :QWidget(parent)这句话(初始化列表中无法直接初始化基类的数据成员,所以你需要在列表中指定基类的构造函数)
最近有点忙,先发一篇我公众号的文章,以下是原文. /********原文********/ 最近很多学习Qt的小伙伴在我的微信公众号私信我,该如何理解下面段代码的第二行QWidget(parent) ...
- ios中解析json对象基类
这个是对上面一篇写的一个解析json对象的基类 @interface BaseObjectFromJson : NSObject + (id) objectWithDict:(NSDictionary ...
- MVC中Spring.net 对基类控制器无效 过滤器控制器无效
比如现在我又一个BaseController作为基类控制器,用于过滤权限.登录判断等作用,其它控制由原本的继承Controller,改为继承BaseController.然后BaseControlle ...
- 使用虚幻引擎中的C++导论(二-UE4基类)
使用虚幻引擎中的C++导论(二) 第一,这篇是我翻译的虚幻4官网的新手编程教程,原文传送门,有的翻译不太好,但大体意思差不多,请支持我O(∩_∩)O谢谢. 第二,某些细节操作,这篇文章省略了,如果有不 ...
- C++中虚基类在派生类中的内存布局
今天重温C++的知识,当看到虚基类这点的时候,那时候也没有太过追究,就是知道虚基类是消除了类继承之间的二义性问题而已,可是很是好奇,它是怎么消除的,内存布局是怎么分配的呢?于是就深入研究了一下,具体的 ...
- 详解C++中基类与派生类的转换以及虚基类
很详细!转载链接 C++基类与派生类的转换在公用继承.私有继承和保护继承中,只有公用继承能较好地保留基类的特征,它保留了除构造函数和析构函数以外的基类所有成员,基类的公用或保护成员的访问权限在派生类中 ...
- 【转载】 C++多继承中重写不同基类中相同原型的虚函数
本篇随笔为转载,原文地址:C++多继承中重写不同基类中相同原型的虚函数. 在C++多继承体系当中,在派生类中可以重写不同基类中的虚函数.下面就是一个例子: class CBaseA { public: ...
- c++中基类与派生类中隐含的this指针的分析
先不要看结果,看一下你是否真正了解了this指针? #include<iostream> using namespace std; class Parent{ public: int x; ...
- C#中派生类调用基类构造函数用法分析
这里的默认构造函数是指在没有编写构造函数的情况下系统默认的无参构造函数 1.当基类中没有自己编写构造函数时,派生类默认的调用基类的默认构造函数例如: ? 1 2 3 4 5 6 7 8 9 10 11 ...
随机推荐
- Codeforces Round #400 (Div. 1 + Div. 2, combined)——ABCDE
题目戳这里 A.A Serial Killer 题目描述似乎很恶心,结合样例和样例解释猜测的题意 使用C++11的auto可以来一手骚操作 #include <bits/stdc++.h> ...
- RAID级别简介
独立硬盘冗余阵列(RAID, Redundant Array of Independent Disks),旧称廉价磁盘冗余阵列(RAID, Redundant Array of Inexpensive ...
- [Cogs728] [网络流24题#3] 最小路径覆盖 [网络流,最大流,二分图匹配]
建图:源点—>边的起点(集合1中的)—>边的终点(集合2中的)—>汇点,所有边权均为1, 计算最大流,最后枚举起点的出边,边权为0的即为匹配上的, 可以这样理解:每条边表示起点和终点 ...
- 华为USG6350防洪墙SNMP最简单功能配置
https://www.cnblogs.com/vincent-liang/p/7785089.html
- quick-cocos2d-x教程7:程序框架内framework文件夹分析
framework是整个框架执行时的实现代码.所以一定要细致看这个文件夹的文件.我们先从framework文件夹中的init.lua分析起走. init.lua文件里,框架初始化时,会自己主动加载下面 ...
- Java 递归、尾递归、非递归、栈 处理 三角数问题
import java.io.BufferedReader; import java.io.InputStreamReader; //1,3,6,10,15...n 三角数 /* * # 1 * ## ...
- powerdesigner 16.5 视图的显示
今天中午为了解说绘图.然后把toolbox跟object brower都关掉了,花了1个小时才找到toolbox 1.object brower显示 直接使用快捷键 ALT+0 2.toolbox(也 ...
- 从零開始学Xamarin.Forms(二) 环境搭建、创建项目
一.环境搭建 Windows下环境搭建: 1.下载并安装jdk.Android SDK和NDK.当然还须要 VS2013 update 2(VS2010.VS2012均可)以上. a. 最新 ...
- Linux下使用popen()执行shell命令【转】
本文转载自:https://my.oschina.net/u/727148/blog/262987 函数原型: #include “stdio.h” FILE popen( const char co ...
- Error-Java-IJ:Imported project refers to unknown jdks JavaSE-1.7
ylbtech-Error-Java-IJ:Imported project refers to unknown jdks JavaSE-1.7 Import from EclipseImported ...