I had this problem that I wrote about this morning where I needed to save a pointer to a member function in one object then call it in another object of the same type as the first. The code would work fine in C++ because it is possible to have a pointer to a non-static member function.

In C#, there are delegates. These are objects that include an object and a function pointer of sorts. When a delegate object is created and used, the programmer does not set the object and function pointer. The programmer sets the delegate to a method and the compiler handles keeping track of the object and function pointer. There is no easy way around this and there is no alternative that can be written in one line of code.

While doing some research today, I discovered reflection. I don’t know the ultimate purpose of reflection but I was able to write code that did what I wanted. What I wanted was to call the proper function in the context of a new and different object. My code will fail in some interesting and yet unknown way of I don’t use the same objects when creating the delegate and then calling it but my initial test worked properly. Here is the code that I threw together using Silverlight and C#.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;
using System.Reflection;

namespace SilverlightApplication1
{   
   public class PersistentInfo
   {
      public PersistentInfo() {}

      /*
       * A delegate type must be defined before an actual delegate variable
       * is declared. This is done here since it is not needed anywhere else
       * in the code.
       */

      public delegate int TheDelegateType( int NewValue );
      
      /*
       * The delegate variable.
       */

      public TheDelegateType TheDelegate = null;

      /*
       * CallbackInContext will call the delegate in the context of the specified
       * object. The Context object MUST be of the same type as was used when the
       * delegate was set or at least one exception will be thrown. This sample
       * code has no error checking.
       */

      public void CallbackInContext( object Context, int Value)
      {
         Type ContextType = Context.GetType();

         MethodInfo TheMethodInfo = 
             ContextType.GetMethod( this.TheDelegate.Method.Name, 
                                    BindingFlags.Public | BindingFlags.Instance );

         Delegate TheDelegateVariable = 
             Delegate.CreateDelegate( typeof( PersistentInfo.TheDelegateType ), 
                                      Context, TheMethodInfo );

         PersistentInfo.TheDelegateType TheDelegate = 
             (PersistentInfo.TheDelegateType)TheDelegateVariable;

         int Result = TheDelegate( Value );
      }
   }

   static public class Global
   {
      static public PersistentInfo Info = new PersistentInfo();
   }

   public class ContextClass
   {
      public ContextClass( int NewValue )
      {
         Value = NewValue;
      }

      public int Value;

      public int TweakValue( int NewValue ) 
      {
         Value = NewValue;
         return Value;
      }

      public void SaveState()
      {
         Global.Info.TheDelegate = TweakValue;
      }

      public void CallDelegateWithValue( int NewValue )
      {
         Global.Info.CallbackInContext( this, NewValue );
      }
   }

   public partial class MainPage : UserControl
   {
      public MainPage()
      {
         InitializeComponent();

         /*
           * The test code happens inside of the MainPage constructor.
          * Create an object and call a function to set the global
          * delegate to "point" to a function in that object.
          * Then create a second object and call the delegate from the
          * first in the context of the second. This works because they
          * are the same type.
          */

         ContextClass FirstObject = new ContextClass( 11 );
         FirstObject.SaveState();
         // FirstObject.Value == 11

         ContextClass SecondObject = new ContextClass( 22 );
         SecondObject.CallDelegateWithValue( 34 );
         /*
          * SecondObject.Value == 34
          * Without the special delegate target object change, the value
          * would be 22 and the FirstObject.Value would have been set
          * to 34 in the previous line of code.
          */
      }
   }
}

This is hard to describe because I copied this from some other place on the web and modified it to work in my situation. All of the work is done in the PersistenInfo class. The other classes are just used for the test. I set some integer values so that I can see the code working properly without having to do a lot of debugging.

All of the real work is done in PersistentInfo.CallbackInContext(). This function accepts an object that represents the new context for the call. This is the object that will be used to call the delegate. I save the typeof() that object and use it to find the method that has the same name as the saved delegate. there will probably be an exception thrown if this doesn’t’ match and I will add error checking later. Leaving the unhandled exception might be best since this cannot be allowed to fail in a final product.

A new delegate is created of the same type as the original delegate but using the Context object and the method info for the now found member method. This is the crux of the code. The delegate variable is turned into a delegate method and called. The new delegate is associated with the right object and things work as expected.

This is slow and dirty because it finds the method by name. This is not at all appropriate for code that must run quickly but it works.