Thanks a lot Joshua!
You're welcome.
Hector E. Gomez Morales wrote: > One question is that style of indentation in the docs intentional?
Forgot about that. It's corrected in my stub.cs.
There's a weird bug in stub that I noticed today. op_Explicit methods are getting added even if they're already in the docs. There are a handful of those duplicated now in CVS. (oops) Easily fixed when the bug is found, as I have stub now checking for duplicate entries.
But, I can't spend more time on this for now. Attached is my stub.cs. There's a new command line option for updating an entire directory of XML files, which should make it easy for anyone to start updating other namespaces.
-- - Joshua Tauberer
http://taubz.for.net
** Nothing Unreal Exists **
// Updater program for syncing Mono's ECMA-style documentation files // with an assembly. // By Joshua Tauberer <[EMAIL PROTECTED]>
using System; using System.Collections; using System.Text; using System.Reflection; using System.Xml; public class Stub { static XmlDocument doc = new XmlDocument(); static int files = 0, additions = 0, deletions = 0; public static void Main(string[] args) { if (args.Length == 0) { Console.WriteLine("Usage: mono stub.exe command"); Console.WriteLine("commands:"); Console.WriteLine("\t--stub type\tCreates a type stub file on stdout."); Console.WriteLine("\t--update basedir type\tUpdates the file for type to stdout, with the file located in basedir/type.Namespace/type.Name.xml, by adding and removing new members as necessary."); Console.WriteLine("\t--regen basedir type\tCreates a type stub file on stdout, importing the Docs nodes from the file located in basedir/type.Namespace/type.Name.xml as appropriate."); Console.WriteLine("\t--updatens nsdir outdir\tUpdates the files in nsdir to outdir."); return; } switch (args[0]) { case "--stub": if (args.Length != 2) throw new InvalidOperationException(); DoStubType(args[1]); break; case "--update": if (args.Length != 3) throw new InvalidOperationException(); DoUpdateType(args[1], args[2]); break; case "--regen": if (args.Length != 3) throw new InvalidOperationException(); DoRegenType(args[1], args[2]); break; case "--updatens": if (args.Length != 3) throw new InvalidOperationException(); DoUpdateNS(args[1], args[2]); break; default: Console.WriteLine("Invalid command. Run with no arguments for help."); break; } Console.Error.WriteLine("Files: {0}, Members Added: {1}, Members Deleted: {2}", files, additions, deletions); } private static void WriteXml(XmlElement element, System.IO.TextWriter output) { XmlTextWriter writer = new XmlTextWriter(output); writer.Formatting = Formatting.Indented; writer.Indentation = 2; writer.IndentChar = ' '; element.WriteTo(writer); output.WriteLine(); } public static void DoStubType(string type) { WriteXml(StubType(type), Console.Out); } public static void DoUpdateType(string basepath, string typename) { Type type = Type.GetType(typename, true); XmlDocument basefile = new XmlDocument(); basefile.PreserveWhitespace = true; basefile.Load(basepath + "/" + type.Namespace + "/" + type.Name + ".xml"); DoUpdateType(basefile, type, Console.Out); } public static void DoUpdateNS(string nspath, string outpath) { foreach (System.IO.FileInfo file in new System.IO.DirectoryInfo(nspath).GetFiles("*.xml")) { XmlDocument basefile = new XmlDocument(); basefile.PreserveWhitespace = true; basefile.Load(nspath + "/" + file.Name); string typename = basefile.SelectSingleNode("Type/@FullName").InnerText; Type type = Type.GetType(typename, false); if (type == null) { Console.Error.WriteLine(typename + " not found."); continue; } using (System.IO.TextWriter output = new System.IO.StreamWriter(outpath + "/" + file.Name)) DoUpdateType(basefile, type, output); } } public static void DoUpdateType(XmlDocument basefile, Type type, System.IO.TextWriter output) { bool mod = false; Console.Error.WriteLine("Updating: " + type.FullName); XmlElement newfile = StubType(type); Hashtable seenmembers = new Hashtable(); // Look for deleted members, remember what members are in the file foreach (XmlElement oldmember in basefile.SelectNodes("Type/Members/Member")) { MemberInfo oldmember2 = GetMember(type, oldmember); if (oldmember2 == null) { // Deleted (or signature changed) Console.Error.WriteLine("Member Deleted: " + oldmember.SelectSingleNode("[EMAIL PROTECTED]'C#']/@Value").InnerText); oldmember.ParentNode.RemoveChild(oldmember); deletions++; mod = true; continue; } if (seenmembers.ContainsKey(oldmember2)) { Console.Error.WriteLine("Duplicate member: " + oldmember.SelectSingleNode("[EMAIL PROTECTED]'C#']/@Value").InnerText); oldmember.ParentNode.RemoveChild(oldmember); deletions++; mod = true; continue; } seenmembers[oldmember2] = 1; } if (!IsDelegate(type)) { Hashtable overrides = new Hashtable(); foreach (Type i in type.GetInterfaces()) foreach (MethodInfo m in type.GetInterfaceMap(i).TargetMethods) overrides[m] = 1; XmlNode members = basefile.SelectSingleNode("Type/Members"); foreach (MemberInfo m in type.GetMembers(BindingFlags.Public|BindingFlags.NonPublic|BindingFlags.Static|BindingFlags.Instance|BindingFlags.DeclaredOnly)) { if (m is Type) continue; if (seenmembers.ContainsKey(m)) continue; // To be nice on diffs, members/properties/events that are overrides or are interface implementations // are not added in. if (m is MethodInfo && !IsNew(overrides, (MethodInfo)m)) continue; if (m is PropertyInfo && !IsNew(overrides, ((PropertyInfo)m).GetGetMethod())) continue; if (m is PropertyInfo && !IsNew(overrides, ((PropertyInfo)m).GetSetMethod())) continue; if (m is EventInfo && !IsNew(overrides, ((EventInfo)m).GetAddMethod())) continue; if (m is EventInfo && !IsNew(overrides, ((EventInfo)m).GetRaiseMethod())) continue; if (m is EventInfo && !IsNew(overrides, ((EventInfo)m).GetRemoveMethod())) continue; XmlElement mm = MakeMember(m); if (mm == null) continue; members.AppendChild( basefile.ImportNode(mm, true) ); members.AppendChild( members.OwnerDocument.CreateWhitespace("\n ") ); Console.Error.WriteLine("Member Added: " + mm.SelectSingleNode("MemberSignature/@Value").InnerText); additions++; mod = true; } } if (mod) files++; WriteXml(basefile.DocumentElement, output); } private static bool IsNew(Hashtable overrides, MethodInfo m) { if (m == null) return true; if (overrides.ContainsKey(m)) return false; MethodInfo b = m.GetBaseDefinition(); if (b == null || b == m) return true; return false; } public static void DoRegenType(string basepath, string typename) { Type type = Type.GetType(typename, true); XmlDocument basefile = new XmlDocument(); basefile.PreserveWhitespace = true; basefile.Load(basepath + "/" + type.Namespace + "/" + type.Name + ".xml"); XmlElement newfile = StubType(type); // Copy old Type/Docs into new doc newfile.ReplaceChild(newfile.OwnerDocument.ImportNode(basefile.SelectSingleNode("Type/Docs"), true), newfile.SelectSingleNode("Docs")); // Copy old Type/Members/Member/Docs into new doc foreach (XmlElement oldmember in basefile.SelectNodes("Type/Members/Member")) { XmlElement newmember = FindMatchingMember(type, newfile, oldmember); if (newmember == null) { Console.Error.WriteLine("Member Deleted: " + oldmember.SelectSingleNode("MemberSignature/@Value").InnerText); continue; } newmember.ReplaceChild(newmember.OwnerDocument.ImportNode(oldmember.SelectSingleNode("Docs"), true), newmember.SelectSingleNode("Docs")); } WriteXml(newfile, Console.Out); } // UPDATE HELPER FUNCTIONS private static XmlElement FindMatchingMember(Type type, XmlElement newfile, XmlElement oldmember) { MemberInfo oldmember2 = GetMember(type, oldmember); if (oldmember2 == null) return null; string membername = oldmember.GetAttribute("MemberName"); foreach (XmlElement newmember in newfile.SelectNodes("Members/[EMAIL PROTECTED]'" + membername + "']")) { if (GetMember(type, newmember) == oldmember2) return newmember; } return null; } private static MemberInfo GetMember(Type type, XmlElement member) { string membertype = member.SelectSingleNode("MemberType").InnerText; // Get list of parameter types for member ArrayList memberparams = new ArrayList(); foreach (XmlElement param in member.SelectNodes("Parameters/Parameter")) memberparams.Add(param.GetAttribute("Type")); // Loop through all members in this type with the same name MemberInfo[] mis = type.GetMember(member.GetAttribute("MemberName"), BindingFlags.Static | BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.DeclaredOnly); foreach (MemberInfo mi in mis) { if (mi is Type) continue; if (GetMemberType(mi) != membertype) continue; ParameterInfo[] pis = null; if (mi is MethodInfo || mi is ConstructorInfo) pis = ((MethodBase)mi).GetParameters(); else if (mi is PropertyInfo) pis = ((PropertyInfo)mi).GetIndexParameters(); if (pis == null) pis = new ParameterInfo[0]; if (pis.Length != memberparams.Count) continue; bool good = true; for (int i = 0; i < pis.Length; i++) if (pis[i].ParameterType.FullName != (string)memberparams[i]) { good = false; break; } if (!good) continue; return mi; } return null; } // CREATE A STUB OF A DOCUMENTATION FILE public static XmlElement StubType(string type) { return StubType(Type.GetType(type, true)); } public static XmlElement StubType(Type type) { string typesig = MakeTypeSignature(type); if (typesig == null) return null; // not publicly visible XmlElement root = doc.CreateElement("Type"); root.SetAttribute("Name", type.Name); root.SetAttribute("FullName", type.FullName); XmlElement sig = doc.CreateElement("TypeSignature"); root.AppendChild(sig); sig.SetAttribute("Language", "C#"); sig.SetAttribute("Value", typesig); XmlElement ass = doc.CreateElement("AssemblyInfo"); root.AppendChild(ass); ass.AppendChild(SimpleElement("AssemblyName", type.Assembly.GetName().Name)); ass.AppendChild(SimpleElement("AssemblyVersion", type.Assembly.GetName().Version.ToString())); ass.AppendChild(SimpleElement("AssemblyCulture", type.Assembly.GetName().CultureInfo.Name)); XmlElement assattributes = MakeAttributes(type.Assembly); if (assattributes != null) ass.AppendChild(assattributes); if (type.BaseType != null) { XmlElement basetype = doc.CreateElement("Base"); root.AppendChild(basetype); basetype.AppendChild(SimpleElement("BaseTypeName", type.BaseType.FullName)); } if (!IsDelegate(type) && !type.IsInterface) { XmlElement interfaces = doc.CreateElement("Interfaces"); root.AppendChild(interfaces); foreach (Type i in type.GetInterfaces()) { XmlElement iface = doc.CreateElement("Interface"); interfaces.AppendChild(iface); iface.AppendChild(SimpleElement("InterfaceName", i.FullName)); } } XmlElement attributes = MakeAttributes(type); if (attributes != null) root.AppendChild(attributes); if (IsDelegate(type)) { root.AppendChild(MakeParameters(type.GetMethod("Invoke").GetParameters())); root.AppendChild(MakeReturnValue(type.GetMethod("Invoke"))); } if (!IsDelegate(type)) { XmlElement members = doc.CreateElement("Members"); root.AppendChild(members); foreach (MemberInfo m in type.GetMembers(BindingFlags.Public|BindingFlags.NonPublic|BindingFlags.Static|BindingFlags.Instance|BindingFlags.DeclaredOnly)) { if (m is Type) continue; XmlElement mm = MakeMember(m); if (mm == null) continue; members.AppendChild( mm ); } } root.AppendChild(MakeDocNode(null, null, true)); return root; } // STUB HELPER FUNCTIONS private static XmlElement SimpleElement(string name, string val) { XmlElement e = doc.CreateElement(name); e.InnerText = val; return e; } private static XmlElement MakeDocNode(ParameterInfo[] parameters, Type returntype, bool returnisreturn) { XmlElement e = doc.CreateElement("Docs"); e.AppendChild(SimpleElement("summary", "To be added.")); if (parameters != null) { foreach (ParameterInfo p in parameters) { XmlElement pe = SimpleElement("param", "To be added."); pe.SetAttribute("name", p.Name); e.AppendChild(pe); } } if (returntype != null && returntype != typeof(void)) { e.AppendChild(SimpleElement(returnisreturn ? "returns" : "value", "To be added.")); } e.AppendChild(SimpleElement("remarks", "To be added.")); return e; } private static XmlElement MakeAttributes(ICustomAttributeProvider attributes) { object[] at = attributes.GetCustomAttributes(false); if (at.Length == 0) return null; bool b = false; XmlElement e = doc.CreateElement("Attributes"); foreach (Attribute a in at) { if (GetTypeVisibility(a.GetType().Attributes) == null) continue; // hide non-visible attributes b = true; // There's no way to reconstruct how the attribute's constructor was called, // so as a substitute, just list the value of all of the attribute's public fields. ArrayList fields = new ArrayList(); foreach (PropertyInfo f in a.GetType().GetProperties(BindingFlags.Public|BindingFlags.Instance)) { if (f.Name == "TypeId") continue; object v = f.GetValue(a, null); if (v == null) v = "null"; else if (v is string) v = "\"" + v + "\""; else if (v is Type) v = "typeof(" + ((Type)v).FullName + ")"; else if (v is Enum) v = v.GetType().FullName + "." + v; fields.Add(f.Name + "=" + v); } string a2 = String.Join(", ", (string[])fields.ToArray(typeof(string))); if (a2 != "") a2 = "(" + a2 + ")"; XmlElement ae = doc.CreateElement("Attribute"); e.AppendChild(ae); string name = a.GetType().FullName; if (name.EndsWith("Attribute")) name = name.Substring(0, name.Length-"Attribute".Length); ae.AppendChild( SimpleElement("AttributeName", name + a2) ); } if (!b) return null; return e; } private static XmlElement MakeParameters(ParameterInfo[] parameters) { XmlElement e = doc.CreateElement("Parameters"); foreach (ParameterInfo p in parameters) { XmlElement pe = doc.CreateElement("Parameter"); e.AppendChild(pe); pe.SetAttribute("Name", p.Name); pe.SetAttribute("Type", p.ParameterType.FullName); if (p.ParameterType.IsByRef) { if (p.IsOut) pe.SetAttribute("RefType", "out"); else pe.SetAttribute("RefType", "ref"); } XmlElement attributes = MakeAttributes(p); if (attributes != null) pe.AppendChild(attributes); } return e; } private static XmlElement MakeParameters(MemberInfo mi) { if (mi is ConstructorInfo) return MakeParameters(((ConstructorInfo)mi).GetParameters()); if (mi is MethodInfo) return MakeParameters(((MethodInfo)mi).GetParameters()); if (mi is PropertyInfo) { ParameterInfo[] parameters = ((PropertyInfo)mi).GetIndexParameters(); if (parameters.Length > 0) return MakeParameters(parameters); else return null; } if (mi is FieldInfo) return null; if (mi is EventInfo) return null; throw new ArgumentException(); } private static XmlElement MakeReturnValue(Type type, ICustomAttributeProvider attributes) { XmlElement e = doc.CreateElement("ReturnValue"); e.AppendChild( SimpleElement("ReturnType", type.FullName) ); if (attributes != null) { XmlElement a = MakeAttributes(attributes); if (a != null) e.AppendChild(a); } return e; } private static XmlElement MakeReturnValue(MemberInfo mi) { if (mi is ConstructorInfo) return null; if (mi is MethodInfo) return MakeReturnValue(((MethodInfo)mi).ReturnType, ((MethodInfo)mi).ReturnTypeCustomAttributes); if (mi is PropertyInfo) return MakeReturnValue(((PropertyInfo)mi).PropertyType, null); if (mi is FieldInfo) return MakeReturnValue(((FieldInfo)mi).FieldType, null); if (mi is EventInfo) return MakeReturnValue(((EventInfo)mi).EventHandlerType, null); throw new ArgumentException(mi.GetType().FullName); } private static XmlElement MakeMember(MemberInfo mi) { if (mi is Type) return null; string sigs = MakeMemberSignature(mi); if (sigs == null) return null; // not publicly visible // no documentation for property/event accessors. Is there a better way of doing this? if (mi.Name.StartsWith("get_")) return null; if (mi.Name.StartsWith("set_")) return null; if (mi.Name.StartsWith("add_")) return null; if (mi.Name.StartsWith("remove_")) return null; if (mi.Name.StartsWith("raise_")) return null; XmlElement me = doc.CreateElement("Member"); me.SetAttribute("MemberName", mi.Name); XmlElement sig = doc.CreateElement("MemberSignature"); me.AppendChild(sig); sig.SetAttribute("Language", "C#"); sig.SetAttribute("Value", sigs); me.AppendChild( SimpleElement("MemberType", GetMemberType(mi)) ); XmlElement a = MakeAttributes(mi); if (a != null) me.AppendChild(a); XmlElement retval = MakeReturnValue(mi); if (retval != null) me.AppendChild(retval); XmlElement parameters = MakeParameters(mi); if (parameters != null) me.AppendChild(parameters); if (mi is FieldInfo && (((FieldInfo)mi).IsLiteral || (((FieldInfo)mi).IsStatic && ((FieldInfo)mi).IsInitOnly))) { object val = ((FieldInfo)mi).GetValue(null); if (val == null) val = "null"; else if (val is Enum) val = val.ToString(); else if (val is IFormattable) val = ((IFormattable)val).ToString(); if (val is string && (string)val != "") me.AppendChild( SimpleElement("MemberValue", (string)val) ); } if (mi is MethodInfo) me.AppendChild(MakeDocNode(((MethodInfo)mi).GetParameters(), ((MethodInfo)mi).ReturnType, true)); else if (mi is ConstructorInfo) me.AppendChild(MakeDocNode(((ConstructorInfo)mi).GetParameters(), null, false)); else if (mi is PropertyInfo) me.AppendChild(MakeDocNode(((PropertyInfo)mi).GetIndexParameters(), ((PropertyInfo)mi).PropertyType, false)); else me.AppendChild(MakeDocNode(null, null, false)); return me; } static bool IsDelegate(Type type) { return typeof(System.Delegate).IsAssignableFrom (type) && !type.IsAbstract; } /// SIGNATURE GENERATION FUNCTIONS static string GetTypeKind (Type t) { if (t.IsEnum) return "enum"; if (t.IsClass || t == typeof(System.Enum)) return "class"; if (t.IsInterface) return "interface"; if (t.IsValueType) return "struct"; throw new ArgumentException(t.FullName); } static string GetTypeVisibility (TypeAttributes ta) { switch (ta & TypeAttributes.VisibilityMask){ case TypeAttributes.Public: case TypeAttributes.NestedPublic: return "public"; case TypeAttributes.NestedFamily: case TypeAttributes.NestedFamORAssem: return "protected"; default: return null; } } static string MakeTypeSignature (Type type) { StringBuilder sig = new StringBuilder(); string visibility = GetTypeVisibility(type.Attributes); if (visibility == null) return null; sig.Append(visibility); sig.Append(" "); if (type.IsAbstract) sig.Append("abstract "); if (type.IsSealed && !IsDelegate(type)) sig.Append("sealed "); if (IsDelegate(type)) { MethodInfo invoke = type.GetMethod ("Invoke"); string arguments = GetMethodParameters(invoke.GetParameters()); string return_value = ConvertCTSName(invoke.ReturnType.FullName); sig.Append(return_value); sig.Append(" "); sig.Append(type.Name); sig.Append("("); sig.Append(arguments); sig.Append(")"); return sig.ToString(); } sig.Append(GetTypeKind(type)); sig.Append(" "); sig.Append(type.Name); if (!type.IsValueType && !type.IsEnum) { if ((type.BaseType != null && type.BaseType != typeof(object)) || type.GetInterfaces().Length > 0) sig.Append(" : "); if (type.BaseType != null && type.BaseType != typeof(object)) { sig.Append(type.BaseType.FullName); if (type.GetInterfaces().Length > 0) sig.Append(", "); } Type [] interfaces = type.GetInterfaces (); for (int i = 0; i < interfaces.Length; i ++){ if (i != 0) sig.Append(", "); sig.Append(interfaces [i].FullName); } } return sig.ToString(); } static string GetFieldVisibility (FieldInfo field) { if (field.IsPublic) return "public"; if (field.IsFamily) return "protected"; return null; } static string MakeFieldSignature (FieldInfo field) { string visibility = GetFieldVisibility (field); if (visibility == null) return null; string type = ConvertCTSName (field.FieldType.FullName); string modifiers = String.Empty; if (field.IsStatic) modifiers += " static"; if (field.IsInitOnly) modifiers += " readonly"; if (field.IsLiteral) modifiers += " const"; return String.Format ("{0}{1} {2} {3}", visibility, modifiers, type, field.Name); } static string GetMethodVisibility (MethodBase method) { if (method.IsPublic) return "public"; if (method.IsFamily) return "protected"; return null; } static string GetMethodParameters (ParameterInfo[] pi) { if (pi.Length == 0) return ""; StringBuilder sb = new StringBuilder (); int i = 0; string modifier; foreach (ParameterInfo parameter in pi) { if (i != 0) sb.Append (", "); if (parameter.ParameterType.IsByRef) { if (parameter.IsOut) sb.Append("out "); else sb.Append("ref "); } string param = ConvertCTSName (parameter.ParameterType.FullName, parameter.ParameterType.IsByRef); sb.Append (param); sb.Append (" "); sb.Append (parameter.Name); i++; } return sb.ToString(); } static string MakeMethodSignature (MethodInfo method) { string visibility = GetMethodVisibility (method); if (visibility == null) return null; string modifiers = String.Empty; if (method.IsStatic) modifiers += " static"; if (method.IsVirtual) { if ((method.Attributes & MethodAttributes.NewSlot) != 0) modifiers += " virtual"; else modifiers += " override"; } if (method.IsAbstract) modifiers += " abstract"; if (method.IsFinal) modifiers += " sealed"; if (modifiers == " virtual sealed") modifiers = ""; string return_type = ConvertCTSName (method.ReturnType.FullName); string parameters = GetMethodParameters (method.GetParameters()); string method_name = method.Name; // operators, default accessors need name rewriting return String.Format ("{0}{1} {2} {3}({4})", visibility, modifiers, return_type, method_name, parameters); } static string MakeConstructorSignature (ConstructorInfo constructor) { string visibility = GetMethodVisibility (constructor); if (visibility == null) return null; string name = constructor.DeclaringType.Name; string parameters = GetMethodParameters (constructor.GetParameters()); return String.Format ("{0} {1}({2})", visibility, name, parameters); } static string MakePropertySignature (PropertyInfo property) { // pick an accessor MethodBase method = property.GetSetMethod (true); if (method == null) method = property.GetGetMethod (true); string visibility = GetMethodVisibility(method); if (visibility == null) return null; string modifiers = String.Empty; if (method.IsStatic) modifiers += " static"; if (method.IsVirtual) { if ((method.Attributes & MethodAttributes.NewSlot) != 0) modifiers += " virtual"; else modifiers += " override"; } if (method.IsAbstract) modifiers += " abstract"; if (method.IsFinal) modifiers += " sealed"; if (modifiers == " virtual sealed") modifiers = ""; string name = property.Name; string type_name = property.PropertyType.FullName; type_name = ConvertCTSName (type_name); string parameters = GetMethodParameters (property.GetIndexParameters()); if (parameters != "") parameters = "[" + parameters + "]"; string accessors = null; if (property.CanRead && property.CanWrite) accessors = "{ set; get; }"; else if (property.CanRead) accessors = "{ get; }"; else if (property.CanWrite) accessors = "{ set; }"; return String.Format ("{0}{1} {2} {3}{4} {5}", visibility, modifiers, type_name, name, parameters, accessors); } static string MakeEventSignature (EventInfo ev) { MethodInfo add = ev.GetAddMethod (); string visibility = GetMethodVisibility(add); if (visibility == null) return null; string modifiers = String.Empty; if (add.IsStatic) modifiers += " static"; if (add.IsVirtual) { if ((add.Attributes & MethodAttributes.NewSlot) != 0) modifiers += " virtual"; else modifiers += " override"; } if (add.IsAbstract) modifiers += " abstract"; if (add.IsFinal) modifiers += " sealed"; if (modifiers == " virtual sealed") modifiers = ""; string name = ev.Name; string type = ConvertCTSName(ev.EventHandlerType.FullName); return String.Format ("{0}{1} event {2} {3}", visibility, modifiers, type, name); } static string MakeMemberSignature(MemberInfo mi) { if (mi is ConstructorInfo) return MakeConstructorSignature((ConstructorInfo)mi); if (mi is MethodInfo) return MakeMethodSignature((MethodInfo)mi); if (mi is PropertyInfo) return MakePropertySignature((PropertyInfo)mi); if (mi is FieldInfo) return MakeFieldSignature((FieldInfo)mi); if (mi is EventInfo) return MakeEventSignature((EventInfo)mi); throw new ArgumentException(mi.ToString()); } static string GetMemberType(MemberInfo mi) { if (mi is ConstructorInfo) return "Constructor"; if (mi is MethodInfo) return "Method"; if (mi is PropertyInfo) return "Property"; if (mi is FieldInfo) return "Field"; if (mi is EventInfo) return "Event"; throw new ArgumentException(); } static string ConvertCTSName (string type, bool shorten) { if (shorten) type = type.Substring (0, type.Length - 1); string retval = ConvertCTSName (type); return retval; } // // Utility function: converts a fully .NET qualified type name into a C#-looking one // static string ConvertCTSName (string type) { if (type.EndsWith ("[]")) return ConvertCTSName(type.Substring(0, type.Length - 2).TrimEnd()) + "[]"; if (type.EndsWith ("&")) return ConvertCTSName(type.Substring(0, type.Length - 1).TrimEnd()) + "&"; if (type.EndsWith ("*")) return ConvertCTSName(type.Substring(0, type.Length - 1).TrimEnd()) + "*"; if (!type.StartsWith ("System.")) return type; switch (type) { case "System.Byte": return "byte"; case "System.SByte": return "sbyte"; case "System.Int16": return "short"; case "System.Int32": return "int"; case "System.Int64": return "long"; case "System.UInt16": return "ushort"; case "System.UInt32": return "uint"; case "System.UInt64": return "ulong"; case "System.Single": return "float"; case "System.Double": return "double"; case "System.Decimal": return "decimal"; case "System.Boolean": return "bool"; case "System.Char": return "char"; case "System.Void": return "void"; case "System.String": return "string"; case "System.Object": return "object"; } return type; } }