fork download
  1. using System;
  2. using System.Reflection;
  3. using System.Collections.Generic;
  4. using System.Globalization;
  5. using System.Linq;
  6. using System.Text;
  7.  
  8. public class Test
  9. {
  10. class MyClass<T> {
  11. public void MyMethod(T a, List<T> b, List<KeyValuePair<T, string>> c) {}
  12. }
  13.  
  14. public static void Main() {
  15. var typesAsStr = new [] {"T", "List`1[T]", "List`1[KeyValuePair`2[T, string]]"};
  16. var myMethods = typeof(MyClass<>)
  17. .GetMethods()
  18. .Where(m => m.Name == "MyMethod")
  19. .ToList();
  20. MethodInfo myMethod = null;
  21. foreach (var candidate in myMethods) {
  22. var paramTypes = candidate.GetParameters().Select(m => m.ParameterType).ToArray();
  23. bool allGood = paramTypes.Length == typesAsStr.Length;
  24. for (var i = 0 ; allGood && i != paramTypes.Length ; i++) {
  25. allGood &= MatchType(typesAsStr[i], paramTypes[i]);
  26. }
  27. if (allGood) {
  28. myMethod = candidate;
  29. break;
  30. }
  31. }
  32. Console.WriteLine("'{0}'", myMethod);
  33. }
  34.  
  35. private enum TokenType {
  36. OpenBraket,
  37. CloseBraket,
  38. Comma,
  39. Tick,
  40. Identifier,
  41. Number
  42. }
  43. private class Token {
  44. public TokenType Type { get; private set; }
  45. public string Text { get; private set; }
  46. public Token(TokenType type, string text) {
  47. Type = type;
  48. Text = text;
  49. }
  50. public override string ToString() {
  51. return string.Format("{0}:{1}", Enum.GetName(typeof(TokenType), Type), Text);
  52. }
  53. }
  54. private static bool DropToken(Queue<Token> tokens, TokenType expected) {
  55. return (tokens.Count != 0) && (tokens.Dequeue().Type == expected);
  56. }
  57. private static bool ReadToken(Queue<Token> tokens, TokenType expected, out string text) {
  58. var res = (tokens.Count != 0) && (tokens.Peek().Type == expected);
  59. text = res ? tokens.Dequeue().Text : null;
  60. return res;
  61. }
  62. private static IEnumerable<Token> Tokenize(IEnumerable<char> str) {
  63. var res = new List<Token>();
  64. var text = new StringBuilder();
  65. foreach (var c in str) {
  66. var pos = "[],`".IndexOf(c);
  67. if ((pos != -1 || char.IsWhiteSpace(c)) && text.Length != 0) {
  68. res.Add(new Token(
  69. char.IsDigit(text[0]) ? TokenType.Number : TokenType.Identifier
  70. , text.ToString())
  71. );
  72. text = new StringBuilder();
  73. }
  74. if (pos != -1) {
  75. res.Add(new Token((TokenType)pos, c.ToString(CultureInfo.InvariantCulture)));
  76. } else if (!char.IsWhiteSpace(c)) {
  77. text.Append(c);
  78. }
  79. }
  80. if (text.Length != 0) {
  81. res.Add(new Token(
  82. char.IsDigit(text[0]) ? TokenType.Number : TokenType.Identifier
  83. , text.ToString())
  84. );
  85. }
  86. return res;
  87. }
  88. public static bool MatchType(string str, Type type) {
  89. var queue = new Queue<Token>(Tokenize(str));
  90. return MatchRecursive(queue, type) && (queue.Count == 0);
  91. }
  92. private static bool MatchRecursive(Queue<Token> tokens, Type type) {
  93. string baseName;
  94. if (!ReadToken(tokens, TokenType.Identifier, out baseName)) return false;
  95. var ranks = new List<int>();
  96. while (type.IsArray) {
  97. ranks.Add(type.GetArrayRank());
  98. type = type.GetElementType();
  99. }
  100. if (type.IsGenericType) {
  101. if (!type.Name.StartsWith(baseName+"`") || !DropToken(tokens, TokenType.Tick)) return false;
  102. string numStr;
  103. int num;
  104. if (!ReadToken(tokens, TokenType.Number, out numStr)
  105. || !int.TryParse(numStr, out num)
  106. || !DropToken(tokens, TokenType.OpenBraket)) return false;
  107. var genParams = type.GetGenericArguments();
  108. if (genParams.Length != num) return false;
  109. for (var i = 0 ; i < num ; i++) {
  110. if (i != 0 && !DropToken(tokens, TokenType.Comma)) return false;
  111. if (!MatchRecursive(tokens, genParams[i])) return false;
  112. }
  113. if (!DropToken(tokens, TokenType.CloseBraket)) return false;
  114. }
  115. foreach (var rank in ranks) {
  116. if (!DropToken(tokens, TokenType.OpenBraket)) return false;
  117. for (var i = 0 ; i != rank-1 ; i++) {
  118. if (!DropToken(tokens, TokenType.Comma)) return false;
  119. }
  120. if (!DropToken(tokens, TokenType.CloseBraket)) return false;
  121. }
  122. return type.IsGenericType || Aliases.Contains(new KeyValuePair<string, Type>(baseName, type)) || type.Name == baseName;
  123. }
  124. private static readonly HashSet<KeyValuePair<string,Type>> Aliases = new HashSet<KeyValuePair<string, Type>> {
  125. new KeyValuePair<string, Type>("bool", typeof(bool)),
  126. new KeyValuePair<string, Type>("byte", typeof(byte)),
  127. new KeyValuePair<string, Type>("sbyte", typeof(sbyte)),
  128. new KeyValuePair<string, Type>("char", typeof(char)),
  129. new KeyValuePair<string, Type>("string", typeof(string)),
  130. new KeyValuePair<string, Type>("short", typeof(short)),
  131. new KeyValuePair<string, Type>("ushort", typeof(ushort)),
  132. new KeyValuePair<string, Type>("int", typeof(int)),
  133. new KeyValuePair<string, Type>("uint", typeof(uint)),
  134. new KeyValuePair<string, Type>("long", typeof(long)),
  135. new KeyValuePair<string, Type>("ulong", typeof(ulong)),
  136. new KeyValuePair<string, Type>("float", typeof(float)),
  137. new KeyValuePair<string, Type>("double", typeof(double)),
  138. new KeyValuePair<string, Type>("decimal", typeof(decimal)),
  139. new KeyValuePair<string, Type>("void", typeof(void)),
  140. new KeyValuePair<string, Type>("object", typeof(object))
  141. };
  142. }
Success #stdin #stdout 0.06s 37320KB
stdin
Standard input is empty
stdout
'Void MyMethod(T, System.Collections.Generic.List`1[T], System.Collections.Generic.List`1[System.Collections.Generic.KeyValuePair`2[T,System.String]])'