Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Customizing interop

lidanger edited this page May 9, 2019 · 2 revisions

默认情况下,当从 Python 中调用 C# 代码时,Python.NET 将只执行以下转换: 将原始 Python 类型转换为 C# 对应类型,将 Python 列表转换为 C# 数组,将以前传递给 C# 的 .NET 对象解包为它们自己。其他所有内容都作为 PyObject 的实例传递。

如果这还不够 (例如,当你有用于 Python 类的 C# 包装器时),你可能希望对从 Python 传递过来的参数执行自定义转换。在这种情况下,您可以实现 IPyArgumentConverter 接口,或者从 DefaultPyArgumentConverter 派生,并重载它的 TryConvertArgument 方法。然后你可以告诉 Python.NET,当试图使用 PyArgConverterAttribute 调用类/程序集中的任何方法时,使用你的转换器。

例如,无论何时需要 int 参数,下面的转换器都会尝试将参数值 (由 Python 传递) 转换为 string,然后将该字符串解析为 int

class CustomArgConverter : DefaultPyArgumentConverter {
    public override bool TryConvertArgument(IntPtr pyarg, Type parameterType, bool needsResolution,
                                            out object arg, out bool isOut) {
        if (parameterType != typeof(int))
            // 默认行为
            return base.TryConvertArgument(pyarg, parameterType, needsResolution, out arg, out isOut);

        bool isString = base.TryConvertArgument(pyarg, typeof(string), needsResolution,
            out arg, out isOut);
        if (!isString) return false;

        int number;
        if (!int.TryParse((string)arg, out number)) return false;
        arg = number;
        return true;
    }
}

它可以附加到这样的类(在 C# 中):

[PyArgConverter(typeof(CustomArgConverter))]
class CustomArgMarshaling {
    public object LastArgument { get; private set; }
    public void CallWithInt(int value) => this.LastArgument = value;
}

在 Python 中:

clrObject = CustomArgMarshaling()
clrObject.CallWithInt("42")

注意,这个特性注释也将用于构造函数和属性访问器。