Introduction
I had posted this question in the C# message board. And thanks to Daniel have found a solution to that.
"Hey Everyone, I am new to C#. I am writing a small application. This application will read a method name from a flat file. Then call the method in another class library with the same name as the one read. Example, I have a method "add" in the flat file and the other library is "Math", then my aplpication should call "Math.add", the other library may change and so the flat file. This is something similar to dlsym that I used in my C/C++ programs on Unix. Can something similar be done here. Thanks in advance, Regards, Jitesh"
Let us understand a sample application of this topic first, in order to understand the topic.
Application
Suppose you wanted to write an engine which searches in a database using some search criteria. Let's call this criteria "SomeFunduCriterea". We have two options for implementing this criteria.
Option 1: Put it into the engine itself. The problem with this is, _you_ have to modify the source for the engine in case the criteria changes. If some one else comes up with some other criteria, he will have to get the code from you and modify it.
Option 2: Make a class library, which is a collection of such criteria. Your engine would simply use this library. Now your engine can be distributed as a binary. And the criteria library as source. So any one could add their own criteria to it and still use the engine without any changes.
Option 2 is always a much better option. The issue here will be when we try to call the functions in our criteria library from the engine. How will the engine know at run time what to call in the criteria library? Let us look at the solution.
Solution
The methods that the engine should call will be in a flat file (mostly an XML file). This will be the input file to the engine. The file will also contain the arguments to the method. We will use the System.Reflection
namespaces' MethodInfo
class to invoke our user method in the criteria class.
How to do this?
We will see a sample example to check out how this can be achieved. We have our user method, in a class called CExternal
.
public class CExternal
{
public CExternal()
{}
public string Fullname(string firstname, string lastname)
{
return (firstname + lastname);
}
}
Our user method here is the FullName
method, which returns concatenation of the two arguments firstname
and lastname
. This class can be in a separate class library.
The next class that we need to write is the CInvoker
, which invokes the method.
public class CInvoker
{
public CInvoker()
{}
public object InvokeMethod (string method, object[] args)
{
CExternal objExternal = new CExternal();
Type typExternal = Type.GetType("MethodInvoke.CExternal");
MethodInfo methodInf = typExternal.GetMethod(method);
object ret = methodInf.Invoke(objExternal, args);
return ret;
}
}
The Simple Steps
- First of all we create an object of the
CExternal
class.
- Get the type of the
CExternal
class.
- On this type object call
GetMethod
. This takes the string name of the method. (Remember our XML file i.e. input to the engine has this name). This method returns us our MethodInfo
object. (MethodInfo
inherits from the MethodBase
class.)
- And finally call the
Invoke
method. We will pass it, our CExternal object
(line 1) and an object[]
of arguments.
And finally the driver for this Invoke class. I.e. our main method in CMain
class.
public class CMain
{
public CMain()
{}
public static void Main()
{
CInvoker ink = new CInvoker();
string[] args = {"Jitesh" , "patil"};
ink.InvokeMethod("Fullname", args);
}
}
Simple isn't it.
Thanks to
- Daniel Turini.
- Microsoft
System.Reflection.MethodBase
and MethodInfo
.
Reference
MSDN link to MethodBase.Invoke()
method.