Avatar of mrichmon
mrichmon
 asked on

Specify delegate from a variable

I have an object (class) that needs to call a function.  Each instance of the class needs to specify which function to call.

I am assuming that delegates would work for this, but I need to have which delegate to call determined via a property of the object (i.e. it is stored in a variable).  The value of that property will be coming from a varchar field in a database.

How do I parse the variable into the name of the delegate to call.  Do I have to use reflection or is there some other way to do this?
.NET ProgrammingASP.NETC#

Avatar of undefined
Last Comment
mrichmon

8/22/2022 - Mon
kaufmed

Why not create an interface that contracts which method will always be called. Then you can have a member of the class that holds a pointer to the function to call:
/////////////////////////
// Interface
/////////////////////////
namespace WindowsFormsApplication2
{
    public interface IMyInterface
    {
        void InvokeDelegate();
    }
}

/////////////////////////
// Class
/////////////////////////
using System;

namespace WindowsFormsApplication2
{
    class MyClass : IMyInterface
    {
        private Action myCallback;

        public MyClass(Action functionToExecute)
        {
            this.myCallback = functionToExecute;
        }

        #region IMyInterface Members

        public void InvokeDelegate()
        {
            if (myCallback != null) this.myCallback();
        }

        #endregion
    }
}

/////////////////////////
// Usage
/////////////////////////
using System;
using System.ComponentModel;
using System.Windows.Forms;

namespace WindowsFormsApplication2
{
    public partial class Form1 : Form
    {
        private MyClass c1;
        private MyClass c2;

        public Form1()
        {
            InitializeComponent();

            this.c1 = new MyClass(Function1);
            this.c2 = new MyClass(Function2);
        }

        public void Function1()
        {
            MessageBox.Show("Function1 executed");
        }

        public void Function2()
        {
            MessageBox.Show("Function2 executed");
        }

        private void Form1_Load(object sender, EventArgs e)
        {
            this.c1.InvokeDelegate();
            this.c2.InvokeDelegate();
        }
    }
}

Open in new window

Jarrod

I would use reflection for this:
IE:
 

public class MyClass
{
    public void Function1()
    {
        //do stuff
    }

    public void Function2()
    {
        //do stuff
    }

    public void Function3()
    {
        //do stuff
    }
}

public class KungFoo
{
     public KungFoo(MyClass paramClass)
     {
          if (true)
          {
               var o = paramClass.GetType().InvokeMember("Function1", BindingFlags.DeclaredOnly Or BindingFlags.Public Or BindingFlags.NonPublic Or BindingFlags.Instance Or BindingFlags.SetProperty, Nothing, obj, New [Object]() {0})

          }
     }
}


//view more here
//http://msdn.microsoft.com/en-us/library/system.type.invokemember(VS.71).aspx

Open in new window

mrichmon

ASKER
kaufmed,

I do not see how this will accomplish what I am asking.  How does that allow me to convert a string into the name of the delegate to invoke.


zadeveloper,

Thanks for the opinion.  I have used reflection before, but was hoping for an alternative.  If I use reflection the functions to call will not be inside the class object.  They will be in multiple other locations, so I would have to reflect each dll.  That is why I would prefer a non-reflection method if possible for this scenario.

all,
If it helps this is a web application, not a windows application - sorry I wasn't clear on that.
All of life is about relationships, and EE has made a viirtual community a real community. It lifts everyone's boat
William Peck
kaufmed

I misinterpreted the question :\

Sorry.
ASKER CERTIFIED SOLUTION
kaufmed

THIS SOLUTION ONLY AVAILABLE TO MEMBERS.
View this solution by signing up for a free trial.
Members can start a 7-Day free trial and enjoy unlimited access to the platform.
See Pricing Options
Start Free Trial
GET A PERSONALIZED SOLUTION
Ask your own question & get feedback from real experts
Find out why thousands trust the EE community with their toughest problems.
mrichmon

ASKER
Yes that is an option - I did not realize you could specify "Delegate" as the type for the value of a dictionary.
mrichmon

ASKER
When I tried this it does not work.  When I do the add I get 2 errors:

Error      1      The best overloaded method match for 'System.Collections.Generic.Dictionary<string,System.Delegate>.Add(string, System.Delegate)' has some invalid arguments
Error      2      Argument '2': cannot convert from 'method group' to 'System.Delegate'      

Some code is attached...
class AccessFunctions
{
	static Dictionary<string, Delegate> functionList;
	
	static AccessFunctions()
	{
		functionList = new Dictionary<string, Delegate>();
		functionList.Add("Function1", AccessFunctions.Function1);
	}
	
	// A sample test function
	public static bool Function1(UserClass user)
	{
		return user.LastName.StartsWith("S");
	}
}


// would want to use later from another class as AccessFunctions.functionList["function1"] and send in the currentUser

Open in new window

⚡ FREE TRIAL OFFER
Try out a week of full access for free.
Find out why thousands trust the EE community with their toughest problems.
mrichmon

ASKER
Okay I fussed with the code some and came up with this to eliminate that error:
class AccessFunctions
{
        private static delegate bool AccessFunction(UserClass user);
        static Dictionary<string, Delegate> functionList;
        
        static AccessFunctions()
        {
                functionList = new Dictionary<string, Delegate>();
                functionList.Add("Function1", new AccessFunction(Function1));
        }
        
        // A sample test function
        public static bool Function1(UserClass user)
        {
                return user.LastName.StartsWith("S");
        }
}

Open in new window

mrichmon

ASKER
Okay to actually be able to compile and then later call the function later I had to change it to the attached code.

class AccessFunctions
{
        internal delegate bool AccessFunction(UserClass user);
        static Dictionary<string, AccessFunction> functionList;
        
        static AccessFunctions()
        {
                functionList = new Dictionary<string, AccessFunction>();
                functionList.Add("Function1", new AccessFunction(Function1));
        }
        
        // A sample test function
        public static bool Function1(UserClass user)
        {
                return user.LastName.StartsWith("S");
        }
}

Open in new window