Thoughts On The Multithread
Wednesday, November 9, 2011
Windows Service follow up
Thursday, February 10, 2011
New sample project coming soon...
ASP.NET Unhandled Exception Handler
Tuesday, September 28, 2010
2 years later...
Friday, October 10, 2008
Daily humor
Wednesday, July 23, 2008
Reflection, Dynamically In C#
On the current project I am working at my job, I need to call web services dynamically. What I am trying to do is add additional functionality to a web page that receives its data from several web services. The web services are called through a proxy web service that puts the data into an XML format that is then past on to the web page and parsed through XSLT transforms into HTML. What I want to do is to be able to add a web service at most anytime without having to touch the web page.
All of the web page configuration is stored in a table, so getting a new web service added is simple enough in that all I need to do is update the proxy web service and add the configuration to the database.
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: namespace Namespace
2: {
3: public class Request
4: {
5: public Request() { }
6:
7: private string name;
8:
9: public string Name
10: {
11: get { return name; }
12: set { name = value; }
13: }
14:
15: private string message;
16:
17: public string Message
18: {
19: get { return message; }
20: set { message = value; }
21: }
22: }
23: }
1: namespace Namespace
2: {
3: public class Response
4: {
5: public Response() { }
6:
7: private string name;
8:
9: public string Name
10: {
11: get { return name; }
12: set { name = value; }
13: }
14:
15: private string message;
16:
17: public string Message
18: {
19: get { return message; }
20: set { message = value; }
21: }
22: }
23: }
Next up, we have our class which has the method we are going to call.
1: namespace Namespace
2: {
3: public class DisplayName
4: {
5: public DisplayName() { }
6:
7: public Response Write(Request req)
8: {
9: // Run once just to show we are actually doing something.
10: Console.WriteLine(string.Format("{0}: {1}", req.Name, req.Message));
11: Response resp = new Response();
12: resp.Name = req.Name;
13: resp.Message = req.Message;
14: return resp;
15: }
16: }
17: }
Finally, our method to process our dynamic call.
1: using System;
2: using System.Reflection;
3:
4: class ReflectionSample
5: {
6: static void Main()
7: {
8: // Get our assembly loaded.
9: Assembly asm = Assembly.Load("Namespace");
10:
11: // Define our main type. This is the type that
12: // we will use to get our actual object.
13: Type mainType = asm.GetType("Namespace.DisplayName");
14:
15: // Create our object based on the type we defined
16: // in the last step.
17: object obj = Activator.CreateInstance(mainType);
18:
19: // Now, we define our request type. The request object
20: // is in the same assembly.
21: System.Type reqTyp = asm.GetType("Namespace.Request");
22:
23: // Next, create our request object.
24: object reqObj = Activator.CreateInstance(reqTyp);
25:
26: // After we create our object, we set the properties.
27: // In my actual application, these properties are set
28: // via a loop, assuming multiple dynamic properties.
29: PropertyInfo piName = reqTyp.GetProperty("Name");
30: piName.SetValue(reqObj, "John", null);
31: PropertyInfo piMess = reqTyp.GetProperty("Message");
32: piMess.SetValue(reqObj, "Hello", null);
33:
34: // The next step is to create the array of parameters
35: // we need to pass into the method we will be calling.
36: // In the case of my application, we only need one.
37: System.Type[] prmTyp = new System.Type[1];
38: prmTyp.SetValue(reqTyp, 0);
39:
40: // The next step is to get our MethodInfo object.
41: // We pass in to GetMethod the name of the method
42: // and the parameter type list.
43: MethodInfo mi = mainType.GetMethod("Write", prmTyp);
44:
45: // Next, we create our actual parameter array.
46: object[] prm = new object[1];
47:
48: // In this case we only have one parameter, so
49: // we set it as our request object.
50: prm.SetValue(reqObj, 0);
51:
52: // Here is where we get tricky. Since we are trying to be
53: // dynamic with this process, we don't want to assume a
54: // definitive type for our return type. Also, in my application
55: // I use response objects that contain multiple properties,
56: // this makes passing multiple properties back easier.
57: System.Type respType = asm.GetType(mi.ReturnType.ToString());
58:
59: // Now, we create an object of our return type.
60: object respObj = Activator.CreateInstance(respType);
61:
62: // Finally, we Invoke our method passing in the parameter array.
63: respObj = mi.Invoke(obj, prm);
64:
65: // This is where we can parse through the properties in the
66: // response object. This is similar to the setting of the
67: // request properties, but there are additional Reflection
68: // methods to parse these dynamically. Here, I'll just use
69: // predefned properties.
70: PropertyInfo piRespName = respType.GetProperty("Name");
71: string name = piRespName.GetValue(respObj, null).ToString();
72: PropertyInfo piRespMessage = respType.GetProperty("Message");
73: string message = piRespMessage.GetValue(respObj, null).ToString();
74:
75: // Prove we actualy did something.
76: Console.WriteLine(string.Format("{0}: {1}", name, message));
77: }
78: }
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.
Friday, June 6, 2008
Visual Studio Debugging with Siteminder
I've seen a few sites mentioning techniques for debugging within a Siteminder world.
This may be a little out dated since it uses Visual Studio 2003, but I'm pretty sure the technique is the same.
Without further ado, here's the steps to do debugging:
- Make sure Visual Studio is not running. It's not mandatory, but it makes it an easier approach.
- Disable Siteminder. This is usually done via config file called WebAgent.conf and is generally located in C:\Program Files\netegrity\webagent\bin\IIS\. Look for a line that looks like EnableWebAgent="YES". Change "YES" to "NO". Note: Case is VERY important!
- Restart IIS. Normally, this is done through the IIS management console, but a reboot will also work. However, that approach won't work later on.
- Start your Visual Studio instance and your Siteminder protected project.
- Next, after the project has fully loaded, change the "NO" back to "YES" and restart IIS. (See why rebooting doesn't work?)
- Now, debug using "Attach to process" and attach to the ASP.NET worker process for your Windows version.
This is a rather simplistic approach, but it works very effectively. It's a pain, but once you get used to it, it becomes second nature. One of these days, I'd like to write a script that automates this, but for now I'll settle for the extra manual steps.
Happy coding!
Update:
In VS 2008, most of these steps are not needed. In particular, steps 1 through 5 are not needed, You just need to make sure that Siteminder is enabled and you attach to the ASP.NET worker process running through IIS. This will not work in the "built in" web server in VS 2008.
Good luck!