为什么Python.NET使用基本方法而不是派生类中的方法?

时间:2018-10-18 06:57:27

标签: c# python .net oop python.net

编辑:此问题将在新版本的pythonnet中修复(合并this拉取请求时)。

我对Python.NET继承有疑问。我有一个包含以下代码的DLL:

using System;

namespace InheritanceTest
{
    public class BaseClass
    {
        public bool Transmit()
        {
            throw new NotImplementedException();
        }
    }

    public class InheritedClass: BaseClass
    {
        public new bool Transmit()
        {
            Console.WriteLine("Success!");
            return true;
        }
    }
}

我希望调用Transmit实例的InheritedClass方法以写入控制台并返回true,而调用Transmit的{​​{1}}方法则抛出一个NotImplementedException。

运行以下python代码时:

BaseClass

我正在使用pythonnet版本2.3.0和.NET Framework 4.6.1。感谢您的帮助!

编辑:this question没有回答。在那里

  

new修饰符指示编译器使用子类实现而不是父类实现。任何不引用您的类但父类的代码都将使用父类实现。

这显然不是这里发生的事情。

编辑2:这似乎是pythonnet库的问题。 The issue is now on github.

1 个答案:

答案 0 :(得分:4)

可以大大提高pythonnet方法的分辨率(在Bind文件中找到的methodbinder.cs方法),恕我直言。无论如何,该方法目前实际上并不关心类型层次结构。

一个简单的解决方案是更改MethodSorter类,以便在对方法进行排序以确定将由Bind调用选择哪个类时,偏爱派生类。

之前:

internal class MethodSorter : IComparer
{
    int IComparer.Compare(object m1, object m2)
    {
        int p1 = MethodBinder.GetPrecedence((MethodBase)m1);
        int p2 = MethodBinder.GetPrecedence((MethodBase)m2);
        if (p1 < p2)
        {
            return -1;
        }
        if (p1 > p2)
        {
            return 1;
        }
        return 0;
    }
}

之后:

internal class MethodSorter : IComparer
{
    int IComparer.Compare(object m1, object m2)
    {
        var me1 = (MethodBase)m1;
        var me2 = (MethodBase)m2;
        if (me1.DeclaringType != me2.DeclaringType)
        {
            // m2's type derives from m1's type, favor m2
            if (me1.DeclaringType.IsAssignableFrom(me2.DeclaringType))
                return 1;

            // m1's type derives from m2's type, favor m1
            if (me2.DeclaringType.IsAssignableFrom(me1.DeclaringType))
                return -1;
        }

        int p1 = MethodBinder.GetPrecedence((MethodBase)m1);
        int p2 = MethodBinder.GetPrecedence((MethodBase)m2);
        if (p1 < p2)
        {
            return -1;
        }
        if (p1 > p2)
        {
            return 1;
        }
        return 0;
    }
}

请注意,我还没有进行广泛的测试,所以我不确定这不会破坏其他功能。正如我所说的那样,整个方法绑定代码似乎很脆弱。