C# 如何为具有空目标的实例方法创建委托?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/951624/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-06 04:04:20  来源:igfitidea点击:

How to create a delegate to an instance method with a null target?

c#.netdelegates

提问by thecoop

I've noticed that the Delegate class has a Target property, that (presumably) returns the instance the delegate method will execute on. I want to do something like this:

我注意到 Delegate 类有一个 Target 属性,它(大概)返回委托方法将在其上执行的实例。我想做这样的事情:

void PossiblyExecuteDelegate(Action<int> method)
{
    if (method.Target == null)   
    {
        // delegate instance target is null
        // do something
    }
    else
    {
         method(10);
         // do something else
    }
}

When calling it, I want to do something like:

调用它时,我想做如下事情:

class A
{
    void Method(int a) {}

    static void Main(string[] args)
    {
        A a = null;
        Action<int> action = a.Method;
        PossiblyExecuteDelegate(action);
    }
}

But I get an ArgumentException (Delegate to an instance method cannot have a null 'this') when I try to construct the delegate. Is what I want to do possible, and how can I do it?

但是当我尝试构造委托时,我得到了一个 ArgumentException(实例方法的委托不能有一个 null 'this')。我想做的事情是否可行,我该怎么做?

采纳答案by thecoop

Ahah! found it!

啊啊!找到了!

You can create an open instance delegate using a CreateDelegateoverload, using a delegate with the implicit 'this' first argument explicitly specified:

您可以使用CreateDelegate重载创建一个开放实例委托,使用一个显式指定隐式“this”第一个参数的委托:

delegate void OpenInstanceDelegate(A instance, int a);

class A
{
    public void Method(int a) {}

    static void Main(string[] args)
    {
        A a = null;
        MethodInfo method = typeof(A).GetMethod("Method");
        OpenInstanceDelegate action = (OpenInstanceDelegate)Delegate.CreateDelegate(typeof(OpenInstanceDelegate), a, method);

        PossiblyExecuteDelegate(action);
    }
}

回答by Adam Robinson

In order to do this you would have to pass a staticmethod to PossiblyExecuteDelegate(). This will give you a nullTarget.

为此,您必须将static方法传递给PossiblyExecuteDelegate(). 这会给你一个nullTarget.

class A
{
    void Method(int a) {}
    static void Method2(int a) {}

    static void Main(string[] args)
    {
        PossiblyExecuteDelegate(A.Method2);

        A a = new A();

        PossiblyExecuteDelegate(a.Method);
    }
}

Edit:It ispossible to pass a delegate to an instance method with no target via reflection, but not using standard compiled code.

编辑:可以通过反射到委托传递给一个实例方法没有目标,但不是使用标准编译的代码。

回答by lidqy

It is possible with Delegate.CreateDelegate, exactly with the overload with the signature: CreateDelegate (Type, object, MethodInfo)

使用 Delegate.CreateDelegate 是可能的,完全使用带有签名的重载: CreateDelegate (Type, object, MethodInfo)

If you specify "null" for the second parameter (target) then you have to put an extra parameter into the delegate type, that specifies the instance type, and when you invoke the delegate, the instance has to be passed as first argument, followed by the "real" parameters of the method.

如果您为第二个参数(目标)指定“null”,那么您必须将一个额外的参数放入委托类型中,该参数指定实例类型,并且当您调用委托时,该实例必须作为第一个参数传递,然后通过方法的“真实”参数。

class Test
{
    public int AddStrings(string a, string b)
    {
        return int.Parse(a) + int.Parse(b);
    }

    static void Main()
    {
        var test = new Test();
        var methodInfo = test.GetType().GetMethod("AddStrings");
        // note the first extra parameter of the Func, is the owner type
        var delegateType = typeof(Func<Test, string, string, int>);
        var del = Delegate.CreateDelegate(delegateType, null, methodInfo);

        var result = (int)del.DynamicInvoke(test, "39", "3");
    }
}