Come creare un delegato di un metodo di istanza con un bersaglio null?

Ho notato che il Delegato di classe ha un Target di proprietà, che (presumibilmente) restituisce l’istanza del delegato metodo di eseguire. Voglio fare qualcosa di simile a questo:

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

Quando la si chiama, voglio fare qualcosa di simile:

class A
{
    void Method(int a) {}

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

Ma ho un ArgumentException (Delegato a un metodo di istanza non può avere un valore null, ‘questo’) quando cerco di costruire il delegato. È quello che voglio fare è possibile, e come posso fare?

  • Perché vuoi fare questo? Sono istanze che sono null?
InformationsquelleAutor thecoop | 2009-06-04



3 Replies
  1. 15

    Ahah! trovato!

    È possibile creare un’istanza aperta delegato utilizzando un CreateDelegate sovraccarico, l’utilizzo di un delegato con l’implicito ‘questo’ primo argomento specificato in modo esplicito:

    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);
        }
    }
    • Sì, come ho modificato la mia risposta, questo è possibile con la riflessione, ma non con standard compilato .NET code. È la vostra preoccupazione che la gente che passa è aggiornati dichiarato delegati?
  2. 1

    Per fare questo è necessario passare un static metodo per PossiblyExecuteDelegate(). Questo vi darà una null Target.

    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: È è possibile passare un delegato di un metodo di istanza con nessun obiettivo attraverso la riflessione, ma non l’utilizzo di standard di codice compilato.

    • Intendo verificare se il metodo di istanza sarebbe stato chiamato un null esempio, se è stato chiamato. Il problema è sempre l’istanza, in primo luogo. Io non ricordo di aver letto qualcosa sull’open delegati, ma non riesco a trovare nascondere né i capelli di ora…
    • Appena trovato i documenti di nuovo – è possibile creare un’istanza aperta delegato utilizzo di un Delegato.CreateDelegate sovraccarico (inviato una risposta con i dettagli)
    • Sì, mi hanno fatto notare che questo sarebbe possibile con la riflessione, ma non con qualsiasi tempo di compilazione-il codice di sicurezza. Risposta a cura.
  3. 0

    È possibile Delegare.CreateDelegate, esattamente il sovraccarico con la firma:
    CreateDelegate (Type, object, MethodInfo)

    Se si specifica “null” per il secondo parametro (target)
    poi devi mettere un parametro supplementare nel tipo di delegato, che specifica il tipo di istanza, e quando si richiama il delegato, l’istanza deve essere passato come primo argomento, seguita dal “reale” parametri del metodo.

    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");
        }
    }

Lascia un commento