TheSwamp
Code Red => .NET => Topic started 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
-
Reflection is your friend on this one.
-
thought it may be :-)
I'll have a play when I get a chance .. haven't delved into reflection programmatically.
-
Apart from reflection, perhaps a map/hash table??
-
Apart from reflection, perhaps a map/hash table??
Mick,
How would you call, say, a string from that std::map/hashtable?
Cheers,
Glenn.
-
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.
-
Kinda like an array of function pointers? Interesting idea.
-
How would you tell said delegate to 'go do it's funky thang'...???
-
@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.
-
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.
-
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
-
or like this :-o
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
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");
}
}
-
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 :-)
-
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
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";
}
}
}
}
-
Another way :-D
[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
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()");
}
}
}
-
Nice work Dave !!
-
Dictionary, map/hashtable,... whatever :D
Nice one Daniel.
-
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.
-
Thanks fellas .. that's heaps for me to play with .. when I get some time to spare.
your blood is worth bottling !