Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
276 views
in Technique[技术] by (71.8m points)

c# - How can I create an open Delegate from a struct's instance method?

I have a struct with a private method that I'd like to invoke. Since I plan to do this in a performance critical section, I'd like to cache a delegate to perform the action. The problem is I can't seem to bind to its method with Delegate.CreateDelegate. The struct in question is not my creation and is used in interaction with a third party library. The struct in question looks like this::

public struct A
{
     private int SomeMethod()
     {
        //body go here
     }
}

And the following code will fail with an "Error binding to target method".

Delegate.CreateDelegate(typeof(Func<A,int>),typeof(A).GetMethod("SomeMethod",BindingFlags.Instance | BindingFlags.NonPublic));

I know I can write an expression tree to perform the action, but it seems odd that I can't use my normal goto for these things the Delegate.CreateDelegate method.

The above code works just fine if A were a class. The issue only arises because A is a struct. MSDN documentation is incorrect for this overload of CreateDelegate as it does work on non-static methods.

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

Interesting problem. From this bug report, it looks like this might be a bug that will be fixed in a future version of .NET: http://connect.microsoft.com/VisualStudio/feedback/details/574959/cannot-create-open-instance-delegate-for-value-types-methods-which-implement-an-interface#details

EDIT: actually, I think this bug report is regarding a different issue, so the behavior you're seeing may not actually be a bug.

From that bug report, I gleaned that there is a work-around if you specify the first argument of your delegate as being passed by reference. Below is a complete working example:

public struct A
{
    private int _Value;

    public int Value
    {
        get { return _Value; }
        set { _Value = value; }
    }

    private int SomeMethod()
    {
        return _Value;
    }
}

delegate int SomeMethodHandler(ref A instance);

class Program
{
    static void Main(string[] args)
    {
        var method = typeof(A).GetMethod("SomeMethod", BindingFlags.Instance | BindingFlags.NonPublic);

        SomeMethodHandler d = (SomeMethodHandler)Delegate.CreateDelegate(typeof(SomeMethodHandler), method);

        A instance = new A();

        instance.Value = 5;

        Console.WriteLine(d(ref instance));
    }
}

EDIT: Jon Skeet's answer here also discusses this issue.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...