TheSwamp

Code Red => .NET => Topic started by: Kerry on January 15, 2008, 03:50:01 PM

Title: Execute Method from String Name.
Post by: Kerry on January 15, 2008, 03:50:01 PM

Has anyone come across an algorithm  to execute a method in an assembly from it's string Name ?
ie

say the string value is "a_103" ; I want to  execute a_103().

OR

be able to assign a method object/ID to a variable name and execute the Method using the Variable Name ?


regards
kwb



Title: Re: Execute Method from String Name.
Post by: Glenn R on January 15, 2008, 03:57:53 PM
Reflection is your friend on this one.
Title: Re: Execute Method from String Name.
Post by: Kerry on January 15, 2008, 04:10:33 PM

thought it may be :-)
I'll have a play when I get a chance .. haven't delved into reflection programmatically.
Title: Re: Execute Method from String Name.
Post by: MickD on January 15, 2008, 04:14:38 PM
Apart from reflection, perhaps a map/hash table??
Title: Re: Execute Method from String Name.
Post by: Glenn R on January 15, 2008, 04:54:35 PM
Apart from reflection, perhaps a map/hash table??

Mick,

How would you call, say, a string from that std::map/hashtable?

Cheers,
Glenn.
Title: Re: Execute Method from String Name.
Post by: MickD on January 15, 2008, 05:10:36 PM
Was just a thought Glenn but can you assign a delegate to a map/hash table? This way the string would be key and the delegate the value if you like.
Title: Re: Execute Method from String Name.
Post by: Chuck Gabriel on January 15, 2008, 06:10:46 PM
Kinda like an array of function pointers?  Interesting idea.
Title: Re: Execute Method from String Name.
Post by: Glenn R on January 15, 2008, 06:18:47 PM
How would you tell said delegate to 'go do it's funky thang'...???
Title: Re: Execute Method from String Name.
Post by: MickD on January 15, 2008, 06:19:43 PM
@Chuck

That's how I'd do it with C/C++, you might have to roll your own though, even a simple hand built linked list would work ok and would still be dynamic.
Title: Re: Execute Method from String Name.
Post by: MickD on January 15, 2008, 06:23:21 PM
How would you tell said delegate to 'go do it's funky thang'...???

hmmm, perhaps when you get the value, pass it to a method that looks after that, something like

MethodToInvokeDelegate(GetsStringValue());

Where the method would be something like -

delegate = getDelegateFromHT(strkey);
delegate.Invoke(); //or something like that.

Title: Re: Execute Method from String Name.
Post by: It's Alive! on January 15, 2008, 07:25:53 PM
Apart from reflection, perhaps a map/hash table??

Maybe something like what we did here?
http://www.theswamp.org/index.php?topic=18355.msg225522#msg225522
Title: Re: Execute Method from String Name.
Post by: It's Alive! on January 15, 2008, 09:16:53 PM
or like this  :-o

Code: [Select]
public class Commands : IExtensionApplication
  {
    public static Dictionary<string, MethodInfo> CommandTable = new Dictionary<string, MethodInfo>();

    [CommandMethod("LoadFile")]
    public void LoadFile()
    {
      Editor ed = AcAp.Application.DocumentManager.MdiActiveDocument.Editor;
      PromptResult pr = ed.GetString("Enter FileName");
      string filename = pr.StringResult;
      if (pr.Status == PromptStatus.OK)
      {
        Load(filename);
      }
    }
    [CommandMethod("ListCommands")]
    public static void ListCommands()
    {
      StringBuilder sb = new StringBuilder();
      foreach (var e in CommandTable)
      {
        sb.Append(e.Key);
        sb.Append(" ");
      }
      Editor ed = AcAp.Application.DocumentManager.MdiActiveDocument.Editor;
      ed.WriteMessage(sb.ToString());
    }

    [CommandMethod("ExecCommand")]
    public static void ExecCommand()
    {
      Editor ed = AcAp.Application.DocumentManager.MdiActiveDocument.Editor;
      PromptResult pr = ed.GetString("Enter Command Name");
      if (pr.Status == PromptStatus.OK)
      {
        MethodInfo method = CommandTable[pr.StringResult.ToUpper()] as MethodInfo;

        if (method != null)
        {
          try
          {
            method.Invoke(method, null);
          }
          catch (System.Exception ex)
          {
            ex.ToString();
          }
        }
      }
    }

    public void Initialize()
    {
      System.AppDomain.CurrentDomain.AssemblyLoad += new AssemblyLoadEventHandler(OnAssemblyLoad);
    }

    public void Terminate()
    {
    }

    void OnAssemblyLoad(Object sender, AssemblyLoadEventArgs e)
    {
      ProcessAssembly(e.LoadedAssembly);
    }

    void Load(String fileName)
    {
      System.Reflection.Assembly.LoadFrom(fileName);
    }

    void ProcessAssembly(Assembly assembly)
    {
      Editor ed = AcAp.Application.DocumentManager.MdiActiveDocument.Editor;

      foreach (Type T in assembly.GetTypes())
      {
        foreach (MethodInfo M in T.GetMethods())
        {
          if (M.IsPublic && M.IsStatic)
          {
            CommandTable.Add(M.Name.ToUpper(), (MethodInfo)M);
          }
        }
      }
    }
  }

In an another assembly

Code: [Select]

public class Class1
  {
    public static void Command1()
    {
      Editor ed = AcAp.Application.DocumentManager.MdiActiveDocument.Editor;
      ed.WriteMessage("From Command1");
    }
    public static void Command2()
    {
      Editor ed = AcAp.Application.DocumentManager.MdiActiveDocument.Editor;
      ed.WriteMessage("From Command2");
    }
  }
Title: Re: Execute Method from String Name.
Post by: Kerry on January 15, 2008, 10:24:58 PM
Thanks Dan ;
I'd anticipated that the methods would be in the same assembly, but a different class.
My initial thought was that I may be able to use this functionality in the Method tester I'm putting together in another thread here ... the selected string from a combo box would be 'invoked' ; saving the necessity of writing a unique case statement block for each assembly.

I'll have a good look when the dust settles locally :-)





Title: Re: Execute Method from String Name.
Post by: SomeCallMeDave on January 15, 2008, 11:04:20 PM
Better late than never, as they say.

Not as elegant as Dan's, but here is my take.

 In a simple Windows Form app with one textbox (default name) and 1 button (default name), it will invoke a method in the Form class or in another class

Code: [Select]
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Reflection;
using System.Windows.Forms;

namespace WindowsFormsApplication1
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
        }

        private void button1_Click(object sender, EventArgs e)
        {
            string Input = textBox1.Text;
            TestClass testClass = new TestClass();


            Type testClassTypes = testClass.GetType();
            Type thisTypes = this.GetType();

            System.Reflection.MethodInfo[] testClassInfo = testClassTypes.GetMethods();
            System.Reflection.MethodInfo[] thisInfo = thisTypes.GetMethods();

            foreach (MethodInfo newInfo in testClassInfo)
            {
                if (newInfo.Name == Input)
                {
                    string returnedData = (string)newInfo.Invoke(testClass, null);
                    MessageBox.Show(returnedData);
                }
            }
            foreach (MethodInfo newInfo in thisInfo)
            {
                if (newInfo.Name == Input)
                {
                    string returnedData = (string)newInfo.Invoke(this, null);
                    MessageBox.Show(returnedData);
                }
            }

           
        }
        public string Test1()
        {
            return "Test1";

        }

        public string Test2()
        {
            return "Test2";

        }

        public class TestClass
        {
            public string Test1()
            {
                return "Test1 from TestClass1";

            }

            public string Test2()
            {
                return "Test2 from TestClass2";

            }
        }


    }
}



Title: Re: Execute Method from String Name.
Post by: It's Alive! on January 15, 2008, 11:14:23 PM
Another way  :-D

Code: [Select]
[assembly: ExtensionApplication(typeof(ExecMethod.Commands))]
[assembly: CommandClass(typeof(ExecMethod.Commands))]

namespace ExecMethod
{
  //
  public delegate void Foo();

  public class Commands : IExtensionApplication
  {
 
    public static Dictionary<string, Delegate> CmdDict = new Dictionary<string, Delegate>();

    [CommandMethod("DOIT")]
    public static void doit()
    {
      CmdDict["w00t"].DynamicInvoke();
      CmdDict["w01t"].DynamicInvoke();
    }

    public void Initialize()
    {
      CmdDict.Add("w00t", new Foo(StuffToExec.command1));
      CmdDict.Add("w01t", new Foo(StuffToExec.command2));
    }

    public void Terminate()
    {
    }

  }
}

another class

Code: [Select]
namespace ExecMethod
{
  public class StuffToExec
  {
    public static void command1()
    {
      Editor ed = AcAp.Application.DocumentManager.MdiActiveDocument.Editor;
      ed.WriteMessage("\nfrom command1()");
    }
    public static void command2()
    {
      Editor ed = AcAp.Application.DocumentManager.MdiActiveDocument.Editor;
      ed.WriteMessage("\nfrom command2()");
    }

  }
}
Title: Re: Execute Method from String Name.
Post by: It's Alive! on January 15, 2008, 11:17:32 PM
Nice work Dave !!

Title: Re: Execute Method from String Name.
Post by: MickD on January 15, 2008, 11:20:13 PM
Dictionary, map/hashtable,... whatever :D

Nice one Daniel.
Title: Re: Execute Method from String Name.
Post by: Bryco on January 16, 2008, 12:00:16 AM
This situation comes into play with a menu,
In vba I had to make a sub for every menu item and when you are dealing with hardware there may be 80 subs that end up calling another function, however I could never figure out how to call a function passing it a string from a menu.
Perhaps the answers in this thread will work for this as well.
Title: Re: Execute Method from String Name.
Post by: Kerry on January 16, 2008, 05:16:14 AM

Thanks fellas .. that's heaps for me to play with .. when I get some time to spare.

your blood is worth bottling !