C# 在C/CLI中创建多个委托/回调并维护DRY

C# 在C/CLI中创建多个委托/回调并维护DRY,c#,delegates,c++-cli,dry,C#,Delegates,C++ Cli,Dry,许多文章包括 已经演示了如何将C++ +CLI委托用作C++回调: typedef void(*SDKUnManagedCB)(void * c, void *c2); 后来 [UnmanagedFunctionPointer(CallingConvention::Cdecl)] delegate void sdkCBStyle(void * c, void *c2); sdkCBStyle^ users = gcnew sdkCBStyle(this, &SDK::UsersCB)

许多文章包括 已经演示了如何将C++ +CLI委托用作C++回调:

typedef void(*SDKUnManagedCB)(void * c, void *c2);
后来

[UnmanagedFunctionPointer(CallingConvention::Cdecl)]
delegate void sdkCBStyle(void * c, void *c2);
sdkCBStyle^ users = gcnew sdkCBStyle(this, &SDK::UsersCB); //2nd parameter is method here in CLI file
IntPtr pUsers = Marshal::GetFunctionPointerForDelegate(users);
GC::KeepAlive(users);  //freed later
GetUsers(static_cast<SDKUnManagedCB>(pUsers.ToPointer())); //GetUsers is unmanaged 3rd party API
后来

[UnmanagedFunctionPointer(CallingConvention::Cdecl)]
delegate void sdkCBStyle(void * c, void *c2);
sdkCBStyle^ users = gcnew sdkCBStyle(this, &SDK::UsersCB); //2nd parameter is method here in CLI file
IntPtr pUsers = Marshal::GetFunctionPointerForDelegate(users);
GC::KeepAlive(users);  //freed later
GetUsers(static_cast<SDKUnManagedCB>(pUsers.ToPointer())); //GetUsers is unmanaged 3rd party API
问题是我找不到传递该函数名的正确函数签名。 F12(转到定义)转到代理的定义 Intellisense还显示了函数签名

MSDN都将字符串作为我尝试使用的第二个参数

Delegate(Object, String)
但当我尝试时:

SDKUnManagedCB CBCreator(String method) {
sdkCBStyle^ piCB = gcnew sdkCBStyle(this, method); // yes my variable names suck...
实时编译已显示错误工具提示:

Error: invalid delegate initializer -- must be a function
我试图查看CreateDelegate,但这看起来很慢

SDKUnManagedCB CBCreator(String^ method) {
    MethodInfo^ info = GetType()->GetMethod(method, BindingFlags::Public | BindingFlags::Instance);

    sdkCBStyle^ piCB = static_cast<sdkCBStyle^>(Delegate::CreateDelegate(sdkCBStyle::typeid, info)); 
    GC::KeepAlive(piCB);   // Yes this is a known leak, it will have to be stored as a member and explictly freed
    return  static_cast<SDKUnManagedCB>((Marshal::GetFunctionPointerForDelegate(piCB)).ToPointer());

}
看起来它可以编译,但是有更简单的方法吗

编辑:它在运行时崩溃, mscorlib.dll中发生类型为“System.ArgumentException”的未处理异常 其他信息:无法绑定到目标方法,因为其签名或安全透明性与委托类型的签名或安全透明性不兼容


我是否需要更多的绑定参数;回调必须是数据封装的成员函数

委托类型安全至关重要,如果回调函数指针签名不同,则没有通用性。从这个问题看不出是否有。如果速度较慢,则只需存储委托对象,以便以后可以再次使用它们,还可以避免您现在的GC::KeepAlive()位置中的错误。@HansPassant是的,为了简洁(以及破解主要功能),我保留了委托句柄的适当内存管理。我不明白你其余的观点;我明确表示我有20个具有相同函数签名的回调。另请参阅我的编辑,它目前不起作用,因此性能问题将不得不等待。