To do all of this, I need to be able to call the methods dynamically using Reflection.
Here's how:
In my application, I use a criteria (or request) object to pass in parameters to the method and a response object on the return. So, here are those objects:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 | namespace Namespace { public class Request { public Request() { } private string name; public string Name { get { return name; } set { name = value; } } private string message; public string Message { get { return message; } set { message = value; } } } } |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 | namespace Namespace { public class Response { public Response() { } private string name; public string Name { get { return name; } set { name = value; } } private string message; public string Message { get { return message; } set { message = value; } } } } |
Next up, we have our class which has the method we are going to call.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | namespace Namespace { public class DisplayName { public DisplayName() { } public Response Write(Request req) { // Run once just to show we are actually doing something. Console.WriteLine(string.Format("{0}: {1}", req.Name, req.Message)); Response resp = new Response(); resp.Name = req.Name; resp.Message = req.Message; return resp; } } } |
Finally, our method to process our dynamic call.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 | using System; using System.Reflection; class ReflectionSample { static void Main() { // Get our assembly loaded. Assembly asm = Assembly.Load("Namespace"); // Define our main type. This is the type that // we will use to get our actual object. Type mainType = asm.GetType("Namespace.DisplayName"); // Create our object based on the type we defined // in the last step. object obj = Activator.CreateInstance(mainType); // Now, we define our request type. The request object // is in the same assembly. System.Type reqTyp = asm.GetType("Namespace.Request"); // Next, create our request object. object reqObj = Activator.CreateInstance(reqTyp); // After we create our object, we set the properties. // In my actual application, these properties are set // via a loop, assuming multiple dynamic properties. PropertyInfo piName = reqTyp.GetProperty("Name"); piName.SetValue(reqObj, "John", null); PropertyInfo piMess = reqTyp.GetProperty("Message"); piMess.SetValue(reqObj, "Hello", null); // The next step is to create the array of parameters // we need to pass into the method we will be calling. // In the case of my application, we only need one. System.Type[] prmTyp = new System.Type[1]; prmTyp.SetValue(reqTyp, 0); // The next step is to get our MethodInfo object. // We pass in to GetMethod the name of the method // and the parameter type list. MethodInfo mi = mainType.GetMethod("Write", prmTyp); // Next, we create our actual parameter array. object[] prm = new object[1]; // In this case we only have one parameter, so // we set it as our request object. prm.SetValue(reqObj, 0); // Here is where we get tricky. Since we are trying to be // dynamic with this process, we don't want to assume a // definitive type for our return type. Also, in my application // I use response objects that contain multiple properties, // this makes passing multiple properties back easier. System.Type respType = asm.GetType(mi.ReturnType.ToString()); // Now, we create an object of our return type. object respObj = Activator.CreateInstance(respType); // Finally, we Invoke our method passing in the parameter array. respObj = mi.Invoke(obj, prm); // This is where we can parse through the properties in the // response object. This is similar to the setting of the // request properties, but there are additional Reflection // methods to parse these dynamically. Here, I'll just use // predefned properties. PropertyInfo piRespName = respType.GetProperty("Name"); string name = piRespName.GetValue(respObj, null).ToString(); PropertyInfo piRespMessage = respType.GetProperty("Message"); string message = piRespMessage.GetValue(respObj, null).ToString(); // Prove we actualy did something. Console.WriteLine(string.Format("{0}: {1}", name, message)); } |
I hope this little sample helps someone else in their struggle to dynamically call code in .NET. Translation to VB shouldn't be too difficult. And as far as I know, this should work in all versions of .NET from 1.0 to 3.5.