c# - 为什么 Python.NET 使用基方法而不是派生类中的方法?
问题描述
编辑:这将在新版本的 pythonnet 中修复(当合并此拉取请求时)。
我对 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,以及抛出 NotImplementedException的Transmit
方法。BaseClass
运行以下 python 代码时:
## setup
import clr
import os
clr.AddReference(os.getcwd() + '\\InheritanceTest.dll')
import InheritanceTest
## method test
base_class = InheritanceTest.BaseClass()
base_class.Transmit() # throws a NotImplementedException as expected
inherited_class = InheritanceTest.InheritedClass()
inherited_class.Transmit() # still throws a NotImplementedException, although it should call InheritedClass.Transmit
我正在使用 pythonnet 版本 2.3.0 和 .NET Framework 4.6.1。谢谢你的帮助!
编辑:这个问题没有回答这个问题。据说那里
new 修饰符指示编译器使用您的子类实现而不是父类实现。任何不引用您的类但父类的代码都将使用父类实现。
这显然不是这里发生的事情。
编辑 2:这似乎是 pythonnet 库的问题。这个问题现在在 github 上。
解决方案
恕我直言,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;
}
}
注意我没有进行广泛的测试,所以我不确定这不会破坏其他东西。正如我所说,整个方法绑定代码似乎很脆弱。
推荐阅读
- file - 如何在系统间缓存中使用 %Net.MailMessage 添加两个或多个文件附件?
- java - 恢复 2 个字符串之间的错误字符
- android - 将搜索栏添加到媒体播放器或迁移到 Exoplayer
- php - OneToMany 关系不列出元素
- c# - C#/SqlServer 内存泄漏
- ios - 为什么添加到场景视图场景中的 3d 对象会随相机一起移动?
- php - PHP如何在特定列中显示数据库中的数据
- spring - Spring Data Rest - 配置 findBy 路径
- python - 如何处理与坐标的碰撞?(在蟒蛇中)
- java - Spring webclient在尝试转换bodyToMono时抛出不受支持的媒体类型异常
, POST 请求