Using Reflection to help formulate design guidelines [Kit George]

So I thought I would share some code I wrote today, to help me formulate a design guideline. I'm trying to define what we should do for 'min' and 'max' as a rule for design guidelines: should it be Min and Max? Or Minimum and Maximum?

The first question of course is: what does the framework do today? That is, do we prefer MaxValue, or MaximumValue? And MinSize, or MinimumSize? So, I wrote up some standard reflection code to look at our own libraries and see what our existing libraries tell me. If you haven't tried Reflection before, I encourage you to do so: I always have a great fun time writing code that analyzes a library (some people are just weird I guess). Note that I only looked at public methods (the BindingFlags option below) becuase even while private members are well-formed, design guidelines typically don't apply to them. I am interested in both static and instance members of course.

Feel free to try this code out and see the results for yourself: I'm still trying to determine what the guideline should be. You can also use the basic principla to quickly discover what your own patterns are and decide if you're being consistent ;-).

using System;
using System.Collections;
using System.IO;
using System.Reflection;

class Test {
static string max = "Max";
static string min = "Min";
static string maximum = "Maximum";
static string minimum = "Minimum";

  public static void Main() {
// so I'm looking at Everett assemblies: but pick your poison
string[] files = Directory.GetFiles(@"C:\WINDOWS\Microsoft.NET\Framework\v1.1.4322", "*.dll");

    ArrayList maxTypes = new ArrayList();
ArrayList maximumTypes = new ArrayList();

    foreach (string file in files) {
Console.Write("Processing {0}", Path.GetFileName(file));
// some of the dll's aren't managed, so I simply ignore them:
// but remember, catching all exceptions is NOT an encouraed practice
try {
Assembly a = Assembly.LoadFile(file);

        Type[] types = a.GetTypes();

        foreach(Type type in types) {
MemberInfo[] members =
type.GetMembers(BindingFlags.Instance | BindingFlags.Static |
BindingFlags.Public);

          foreach(MemberInfo mi in members) {
// basic string formattig for nice display, always fun
string name = String.Format("{0,-40}{1,-35}{2}",
type.Namespace, type.Name, mi.Name);

            // just decide which list to add the issues to
if (mi.Name.StartsWith(maximum) || mi.Name.StartsWith(minimum)) {
if (maximumTypes.IndexOf(name) < 0) {
maximumTypes.Add(name);
}
} else if (mi.Name.StartsWith(max) || mi.Name.StartsWith(min)) {
if (mi.Name.Length == 3 || Char.IsUpper(mi.Name[3])) {
if (maxTypes.IndexOf(name) < 0) {
maxTypes.Add(name);
}
}
}
}
}
} catch {
//you could do something more fancy here if you wanted
Console.Write(" ... error!!!");
}
Console.WriteLine();
}

    // write the lists to two files,
// one being all the short forms, one being the long forms
WriteAllLines("maxTypes.txt", maxTypes, max, min);
WriteAllLines("maximumTypes.txt", maximumTypes, maximum, minimum);
}

  static void WriteAllLines(string file, ArrayList entries, string m1, string m2) {

    int dupeVals = 0;

    // Many types contain a Max AND a Min: From an accounting perspective
// I chose to ignore this, so I get rid of dupes
// I methodized the code here since I wanted to go through the list in
// both directions. I'm not panicking over perf here, clearly!
dupeVals += GetDuplicatedValues(entries, m1, m2);
dupeVals += GetDuplicatedValues(entries, m2, m1);

    using (StreamWriter sw = new StreamWriter(file)) {
sw.WriteLine("Total Entries in this list = {0}", entries.Count);
sw.WriteLine("Duplicated Entries in this list = {0}", dupeVals);
sw.WriteLine("Total Unique Values in this list = {0}", entries.Count - dupeVals);
sw.WriteLine("--------------------------------");

      // check out V2.0, it makes this WAY easier: File.WriteAllLines
foreach (string s in entries) {
sw.WriteLine(s);
}
sw.WriteLine("--------------------------------");
}
}

  // this code is to basically ignore
static int GetDuplicatedValues(ArrayList entries, string m1, string m2) {
int dupeVals = 0;

    for(int i=0;i<entries.Count;i++) {
string s1 = (string)entries[i];
int found = s1.IndexOf(m1);

      if (found >= 0) {
for(int j=i+1;j<entries.Count;j++) {
string s2 = (string)entries[j];
if ((s1.Length == s2.Length) && (found + m1.Length <= s1.Length)) {
if (s1.Substring(0,found) == s2.Substring(0,found) &&
(s1.Substring(found + m1.Length) ==
s2.Substring(found + m1.Length)) &&
s2.Substring(found, m1.Length) == m2) {
dupeVals++;
}
}
}
}
}
return dupeVals;
}
}