传递 ref class 成员函数作为参数

Passing ref class member function as a parameter

我正在尝试创建一个包装器,允许 System::Task 在一个衬里中创建对象。到目前为止,我有以下工作 -

ref class TaskRunner abstract sealed
{
public:
    generic<typename TArg0>
    static Task^ Create(Action<TArg0>^ f, TArg0 arg0) {
        return Task::Run((gcnew BindAction1<TArg0>(f, arg0))->binder);
    }
private:
    generic<typename TArg0>
    ref class BindAction1
    {
        initonly TArg0 _arg0;
        Action<TArg0>^ const f;
        void _() { return f(_arg0); }
    public:
        initonly Action^ binder;
        BindAction1(Action<TArg0>^ f, TArg0 arg0) : f(f), _arg0(arg0) {
            binder = gcnew Action(this, &BindAction1::_);
        }
    };
}

可以通过-

调用
auto task = TaskRunner::Create(gcnew Action<TArg0>(this, &Class::Function), arg0);

但是我想消除手动创建操作的需要。 IE。修改 Create 使调用看起来像-

auto task = TaskRunner::Create(this, &Class::Function, arg0);

并在 Create 中调用 gcnew Action(obj, func)。我不知道这是否可能。如果是这样,我将如何声明创建的参数?

实际上它们需要与 Action 委托相同。查看系统库 Action 似乎需要 System::Object 和 System::IntPtr 但我无法使用它们作为参数来使其工作。

*更新 - 感谢 IllidanS4 提供完整的答案以及您帮助完成这项工作。对于任何试图在他的答案中使用代码的人来说,Visual Studio 2015 中似乎存在一个编译器错误,它需要为每个参数链长度覆盖 delegate_type。

来自 ECMA-372:

A program that attempts to take the address of a member function of a non-native class in any context other than in the creation of a delegate, is ill-formed. There is no pointer-to-member representation for members of non-native classes.

不幸的是,这意味着 &Class::Function 无效。在我看来,这个限制是没有用的,因为 CIL 中的 ldftn 指令正是在委托构造中编译成的指令。遗憾的是,C++/CLI 中缺少一个 "pointer to managed function" 类型,尽管它显然存在于 CIL 中。

所以不,方法必须包含在委托中传递。但是,如果你对宏开放,你可以使用这样的东西:

#define CreateTask(obj, func, arg) TaskRunner::Create(gcnew System::Action<decltype(arg)>(obj, func), arg)

编辑:使它也适用于 Func 情况有点棘手,但它也适用于某些模板:

template <class Ret, class... Args>
struct delegate_type
{
    using type = System::Func<Args..., Ret>;
};

template <class... Args>
struct delegate_type<void, Args...>
{
    using type = System::Action<Args...>;
};

#define CreateTask(obj, func, arg) TaskRunner::Create(gcnew delegate_type<decltype(obj->func(arg)), decltype(arg)>::type(obj, &func), arg)

只是不要将它与 &Class::Function 一起使用,而是传递 Class::Function