C# delegate not bound to an instance?

后端 未结 4 1945
盖世英雄少女心
盖世英雄少女心 2021-01-04 08:47

Is there a way to store a delegate without binding it to an object like how you can with a MethodInfo? Right now I am storing a MethodInfo so I can give it the object to cal

相关标签:
4条回答
  • 2021-01-04 09:08

    What you want is called an open instance delegate. It isn't supported directly in the C# language, but the CLR supports it.

    Basically, an open instance delegate is the same as a normal delegate, but it takes an extra parameter for this before the normal parameters, and has a null target (like a delegate for a static method). For instance, the open instance equivalent of Action<T> would be:

    delegate void OpenAction<TThis, T>(TThis @this, T arg);
    

    Here's a complete example:

    void Main()
    {
        MethodInfo sayHelloMethod = typeof(Person).GetMethod("SayHello");
        OpenAction<Person, string> action =
            (OpenAction<Person, string>)
                Delegate.CreateDelegate(
                    typeof(OpenAction<Person, string>),
                    null,
                    sayHelloMethod);
    
        Person joe = new Person { Name = "Joe" };
        action(joe, "Jack"); // Prints "Hello Jack, my name is Joe"
    }
    
    delegate void OpenAction<TThis, T>(TThis @this, T arg);
    
    class Person
    {
        public string Name { get; set; }
    
        public void SayHello(string name)
        {
            Console.WriteLine ("Hi {0}, my name is {1}", name, this.Name);
        }
    }
    

    Have a look at this article for more details.

    0 讨论(0)
  • 2021-01-04 09:18

    Why not simply

    Action<T, string> unbound = (This, str) => This.Method(str);
    

    so you can

    unbound(instanceA, "hello");
    unbound(instanceB, "world");
    

    or even

    Action<string> bound = str => unbound(instanceC, str);
    
    0 讨论(0)
  • 2021-01-04 09:25

    A delegate is essentially just a MethodInfo (actually, a MethodBase) and an object reference, with some internal pointers for performance. So if you have a MethodInfo, you essentially have an unbound delegate. What is your specific use case?

    0 讨论(0)
  • 2021-01-04 09:30

    You can use the Delegate.CreateDelegate method to create a strongly-typed delegate for a MethodInfo.

    If you don't know the method's signature at compile-time, you can either create a Func<...> using Reflection, or create a lambda expression that invokes the MethodInfo:

    MethodInfo methodInfo = ...;
    object thisObj = ...;
    Func<object[]> callMethod = args => methodInfo.Invoke(thisObj, args);
    

    (This is called currying)

    Note that this will still have the performance hit from reflection every time the delegate is called, unlike Delegate.CreateDelegate.

    0 讨论(0)
提交回复
热议问题