2014-11-04 138 views
4

我使用Python.NET来加载C#程序集以从Python调用C#代码。这工作得干净利索,但是我有一个问题,调用看起来像这样的方法:在Python中使用Python.NET创建C#可空的Int32(使用Python.NET)以可选的int参数调用C#方法

内Our.Namespace.Proj.MyRepo的方法:

OutputObject GetData(string user, int anID, int? anOptionalID= null) 

我可以拨打电话进行的情况下方法可选的第三个参数是存在的,但不知道要传递第三个参数以匹配空情况。

import clr 
clr.AddReference("Our.Namespace.Proj") 
import System 
from Our.Namespace.Proj import MyRepo 

_repo = MyRepo() 

_repo.GetData('me', System.Int32(1), System.Int32(2)) # works! 

_repo.GetData('me', System.Int32(1)) # fails! TypeError: No method matches given arguments 

_repo.GetData('me', System.Int32(1), None) # fails! TypeError: No method matches given arguments 

IPython的笔记本电脑表示最后的参数应该是类型:

System.Nullable`1[System.Int32] 

只是不知道如何创建一个对象,将空的情况下匹配。

关于如何创建一个C#识别的空对象的任何建议?我认为传递本地Python无效,但它不。

+2

我不知道Python.NET,但似乎,当你通过无它,它可能只搜索米具有参考类型参数的方法。你至少可以在没有最后一个参数的情况下尝试一个超载(并且可能会有另一个超载,最后一个参数是'object'以允许传递None(如果有效的话),然后调用第一个方法并使用最后一个参数'as int?')。 – IllidanS4 2014-11-07 17:04:38

+1

结束重构C#端以重载方法(一个没有第三个参数,另一个没有第三个参数)。 Python.NET处理这个罚款。缺点是我必须有条件地根据最后一个参数的存在来调用两种方法之一。我会尝试建议让C#端的第三个重载案例的最后一个参数为'object',以允许传递None。谢谢! – skulz00 2014-11-07 18:01:43

回答

2

[编辑]

这已合并pythonnet:

https://github.com/pythonnet/pythonnet/pull/460


我跑进可空基元的同样的问题 - 这在我看来,没有按Python.NET不支持这些类型。我解决此问题得到了由Python.Runtime.Converter.ToManagedValue()(的\ src \运行\ converter.cs)添加以下代码

if(obType.IsGenericType && obType.GetGenericTypeDefinition() == typeof(Nullable<>)) 
{ 
    if(value == Runtime.PyNone) 
    { 
     result = null; 
     return true; 
    } 
    // Set type to underlying type 
    obType = obType.GetGenericArguments()[0]; 
} 

我把这个代码正下方

if (value == Runtime.PyNone && !obType.IsValueType) { 
    result = null; 
    return true; 
} 

https://github.com/pythonnet/pythonnet/blob/4df6105b98b302029e524c7ce36f7b3cb18f7040/src/runtime/converter.cs#L320

+0

你是说你修改了Python.NET源代码吗? – skulz00 2014-12-05 22:16:42

+1

是的,我指的是http://sourceforge.net/p/pythonnet/code/147/tree/trunk中的Python.NET源代码。 – antchi 2014-12-08 01:15:02

+0

明白了。谢谢!我将总结这个问题并发布到http://sourceforge.net/p/pythonnet/bugs/,以便它可以集成到下一个版本中。 – skulz00 2014-12-08 14:37:15

2

我没有办法来测试这一点,但尝试

_repo.GetData('me', System.Int32(1), System.Nullable[System.Int32]()) 

既然你说的可选参数为Nullable,你需要创建在C#代码Int32类型的新Nullable对象,或new System.Nullable<int>()

我假设第一个失败的例子会工作,因为这是可选参数在C#中的工作方式;调用函数而不指定参数。

+0

感谢您的建议。当我尝试创建'System.Nullable [System.Int32]()'时,即使在调用GetData之外,我也得到一个'TypeError:no constructor match given arguments'。我也尝试传递'System.Nullable [System.Int32]'并且给了我'ArgumentException:'System.RuntimeType'类型的对象不能转换为类型'System.Nullable \'1 [System.Int32]'。 ' – skulz00 2014-11-05 14:16:27

+0

奇怪。我不熟悉Python的语法,不确定那里有什么'1'。希望有人比我更聪明可以破解这个坚果。我原本以为你使用IronPython,你可能想尝试一下,因为它似乎更好地处理可选参数。 – ToastyMallows 2014-11-05 14:34:03

+0

这不是Python语法,这是泛型类型的.NET语法 - '1表示1种类型参数。 – IllidanS4 2014-11-07 16:58:51

1

你要通过参数传递给泛型函数System.Nullable[System.Int32](0)

相关问题