zoukankan      html  css  js  c++  java
  • 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.1scriptingPyengineer";
            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

  • 相关阅读:
    flex 布局 shrink 属性
    flex 布局 flex-grow 属性
    flex 布局 flex-basis 属性
    flex 布局 justify-content 对齐的图解
    CSS定位要点笔记
    CSS浮动要点笔记
    CSS选择器要点笔记
    eslint no-unused-vars 解决办法
    NodeJs使用Promise解决多层异步调用的简单学习
    windows10 搭建 NTP 时间服务器
  • 原文地址:https://www.cnblogs.com/jjseen/p/5752359.html
Copyright © 2011-2022 走看看