I’m paranoid about time, especially when it comes to getting places on time. A good friend of mine once warned me, when planning a trip to the airport: “Plan as if three things will go wrong.” I never understood this concept. I just give myself lots of time getting to the airport-more so now that we’re subjected to the 3-ounce rule of travel toiletries.
So, when leaving Minneapolis for a flight back west a few weeks ago, I found myself at the Northwest Airlines club several hours before my flight. At this particular club, they have tiny work booths, separated from each other with little walls that are maybe four feet tall and two feet deep. Each carrel is three feet wide or so, and there’s a small aisle between back-to-back booths. That is, the backs of the two chairs on either side of the aisle are relatively close. (I describe the physical dimensions only to give you a visual layout so that you can more appropriately imagine the ugliness that ensued.)
I settled in at around 6:30AM, and my flight was scheduled for 9AM. I checked e-mail, wrote a column (perhaps one like this), and frittered away the time until boarding, like every other weary traveler. Finally, around 8:30AM, I gathered my stuff, retentively wound up the power cords, and got ready to trudge to the gate. I turned to leave, and a flicker on the screen in the booth behind me caught my eye. I saw a 30-ish guy, disheveled and unshaved, hunched over his laptop. I couldn’t help myself. My eyes were drawn to see what was moving on his screen (I should learn better). What was seen, can never be unseen-serious, hard-core, porn. Need I say this? Listen, people: The Northwest Airlines lounge is not the place for hardcore porn! I won’t discuss what might be the correct place, but this one surely wasn’t. I felt like slapping the guy on the back of his head, like TV moms do when the kids misbehave. I suppose, in some small way, I should have been appreciative-at least the guy wasn’t watching the porn on the plane. Oh, wait. Maybe he did.
One might argue that I shouldn’t have looked in the first place. Really, is there any way to resist the flicker of live action on a neighbor’s laptop screen? Don’t you just need to know? So, I suppose, I brought this on myself. It’s an image (not the porn) that I’ve had a hard time getting out of my head-the sad lonely guy, sitting in the Northwest Airlines club, waiting for his flight, passing the time with X-rated entertainment. Not a pretty sight.
Now that you share that lovely image, might we move on? Can we get beyond this? As with real life, there’s a time and place for everything in programming, and I recently faced a time-based challenge-I needed to retrieve a list of all the public methods that have a particular signature in an assembly. (The reason for this need isn’t important-there are other ways to solve the original purpose for this search, but for now, just go with me. We need to find all the methods that match the particular signature.)
As with all such tasks, Reflection is the answer. (I love Reflection. It just seems like such an elegant, if somewhat inefficient, solution to so many problems.)
Imagine that I need to find all methods (not properties, not events, just methods) that return an integer, and accept two integers as input values. You might write code like that shown in Listing 1. This code uses standard Reflection techniques: Given a specific Type, the code loops through all the methods of the type, and if the number and types of the parameters and return value match the requirements, the code adds the MethodInfo instance to an output array.
Although this code works, there may be a better way, especially if the criteria were more complex. The System.Type class provides a FindMembers method that may make things easier (and if not easier, then perhaps just “neater”). The FindMembers method lets you specify the kind of member you’re looking for (method, property, event, and so on), and flags indicating which instances of the members you want (public, private, static, instance, and so on). In addition, you specify the address of a callback procedure that performs the matches-the .NET Runtime calls this procedure for each member that otherwise matches the criteria you’ve specified, and this procedure can check parameters and return types for a match. Finally, you can specify a final parameter that can be any information you need to pass to the search procedure (possibly information specific for this particular search, if you’re using the same callback procedure for multiple searches). The callback procedure receives each matching MemberInfo instance in turn, and returns a Boolean value indicating whether the instance meets your needs. Listing 2 shows a possible rewrite for the previous code-it’s not any shorter, it’s not much simpler, but it does avoid looping through all the methods yourself. Instead, the .NET Runtime takes care of that, calling the sample’s Filter method for any matching method it finds.
To call either version of the procedure, you could write test code like this (assuming that you wanted to look in a local class named YourClass):
' Visual Basic
Dim methods As MemberInfo() = _
FindMethods(GetType(YourClass))
For Each method As MethodInfo In methods
Debug.WriteLine(method.Name)
Next
// C#
MemberInfo[] methods =
FindMethods(typeof(Class1));
foreach (MethodInfo method in methods)
{
Debug.WriteLine(method.Name);
}
Is the FindMembers method faster than looping through the members yourself? It could be, but I doubt it’s a measurable difference. Is it simpler? That depends-if you need to repeat the search across multiple different types, using different criteria, it might very well be. Using the FindMembers method, you factor out the code that provides the logic for the match-in general, that’s a good idea.
As with airline lounge activities, there’s a place and time for each technique. (You know, I try. I really try. I wanted to retell the events of that June morning in Minneapolis, and I wanted to talk about Reflection. I tried many angles to link them. I even passed through the “I saw my Reflection in his laptop screen…” but that seriously didn’t work. So I’m just going with this somewhat inelegant linkage.) Think about whether you’ll benefit from the elegance of the FindMembers method, or if its callback mechanism just gets in your way. In my experience, calling the FindMembers method makes your Reflection code maintainable, and more readable. It’s the right solution, in the right time and place. And keep your adult entertainment at home-it’s never the right time and place for that in public.