在Python for.NET中实现一个C#接口

在Python for.NET中实现一个C#接口,c#,python,interface,python.net,pythonnet,C#,Python,Interface,Python.net,Pythonnet,我得到了一个用C#编写的库,我正试图使用Python for.NET调用它 我需要一个实例的主类具有如下构造函数: GDhuClient(IGDhuSettings) 没有(公开的)类实现IGDhuSettings接口。当我创建Python类来实现它时,例如 class PyGDhuSettings(IGDhuSettings): ... 我得到TypeError:如果我没有\uuuu new\uuuuu方法,或者如果我以正常方式定义了一个参数,则接口只接受一个参数: def __n

我得到了一个用C#编写的库,我正试图使用Python for.NET调用它

我需要一个实例的主类具有如下构造函数:

GDhuClient(IGDhuSettings)
没有(公开的)类实现
IGDhuSettings
接口。当我创建Python类来实现它时,例如

class PyGDhuSettings(IGDhuSettings):
    ...
我得到
TypeError:如果我没有
\uuuu new\uuuuu
方法,或者如果我以正常方式定义了一个参数,则接口只接受一个参数:

def __new__(cls):
    return super().__new__(cls)
如果我尝试将接口实例化为类,则会得到相同的错误(没有参数或>1个参数),或者如果传递单个参数,
未实现IGDhuSettings

看这个,

使用系统;
运用系统反思;
使用System.Runtime.InteropServices;
名称空间Python.Runtime
{
/// 
///提供反射接口类型的实现。托管
///接口在Python中由实际的Python类型对象表示。
///这些类型对象中的每一个都与此
///类,它提供Python类型的实现。
/// 
内部类接口对象:ClassBase
{
内部结构信息;
内部接口对象(tp型):基座(tp)
{
var coclass=(CoClassAttribute)Attribute.GetCustomAttribute(tp,cc_attr);
if(coclass!=null)
{
ctor=coclass.coclass.GetConstructor(Type.EmptyTypes);
}
}
私有静态类型cc_attr;
静态接口对象()
{
cc_attr=typeof(CoClassAttribute);
}
/// 
///为反射的接口类型实现新的。
/// 
公共静态IntPtr tp_新(IntPtr tp、IntPtr args、IntPtr kw)
{
var self=(InterfaceObject)GetManagedObject(tp);
int nargs=Runtime.PyTuple_Size(args);
类型=self.Type;
对象对象对象;
if(nargs==1)
{
IntPtr inst=Runtime.PyTuple_GetItem(args,0);
var co=GetManagedObject(inst)作为CLR对象;
if(co==null | |!type.IsInstanceOfType(co.inst))
{
Exceptions.SetError(Exceptions.TypeError,$“对象未实现{type.Name}”);
返回IntPtr.Zero;
}
obj=co.inst;
}
else if(nargs==0&&self.ctor!=null)
{
obj=self.ctor.Invoke(null);
if(obj==null | |!type.IsInstanceOfType(obj))
{
Exceptions.SetError(Exceptions.TypeError,“CoClass默认构造函数失败”);
返回IntPtr.Zero;
}
}
其他的
{
Exceptions.SetError(Exceptions.TypeError,“接口只接受一个参数”);
返回IntPtr.Zero;
}
返回CLRObject.GetInstHandle(obj,self.pyHandle);
}
}
}
我看不到一种在Python中实现C#接口的方法,它既没有一个CoClass(没有定义CoClass),也没有一个已经实现它的类

这里有没有我遗漏的细微差别,或者这是Python for.NET的一个限制


关于GitHub的讨论:

我发现我需要将名称空间字段添加到实现接口的Python类中。据我所知,该字段表示实现该接口的Python类的.NET命名空间

举个例子。我制作了一个具有以下界面的C#库:

public interface ITestInterface
{
    string StringAdd(string text, int number);
}
public static string InvokeStringAdd(ITestInterface testInterface, string text)
{
    return "*** " + testInterface.StringAdd(text, 7) + " ***";
}
class TestInterfaceSubClass(ITestInterface):
    __namespace__ = "MyNameSpace"

    def StringAdd(self,text,x):
        return 'My text <{}> with number <{}>'.format(text, x)
还有一个消耗接口的简单静态函数:

public interface ITestInterface
{
    string StringAdd(string text, int number);
}
public static string InvokeStringAdd(ITestInterface testInterface, string text)
{
    return "*** " + testInterface.StringAdd(text, 7) + " ***";
}
class TestInterfaceSubClass(ITestInterface):
    __namespace__ = "MyNameSpace"

    def StringAdd(self,text,x):
        return 'My text <{}> with number <{}>'.format(text, x)
然后在Python方面,我定义了以下实现接口的类:

public interface ITestInterface
{
    string StringAdd(string text, int number);
}
public static string InvokeStringAdd(ITestInterface testInterface, string text)
{
    return "*** " + testInterface.StringAdd(text, 7) + " ***";
}
class TestInterfaceSubClass(ITestInterface):
    __namespace__ = "MyNameSpace"

    def StringAdd(self,text,x):
        return 'My text <{}> with number <{}>'.format(text, x)
返回

*** My text <My Text> with number <7> ***
***带编号的我的文本***

最后请注意,python类TestInterfaceSubClass被赋予名称空间“MyNameSpace”。这意味着重新评估Jupyter笔记本中的类定义代码将导致.NET端的名称空间冲突,因此您必须给它一个不同的名称空间值或重新启动内核。

我没有使用Python for.NET进行任何严肃的操作,但我可以看出这可能是一个有意的限制。您的Python代码不在.NET中运行,因此它必须为接口的每个方法构建一个代理方法,这可能是缓慢而脆弱的,因此他们可能希望您修改设计,以便只传递一个委托,或者改用IronPython?我几乎是在我的dll上创建事件之类的东西,这样我就可以在python上使用一个实现了!救了我的命:)