1: public class RinhaMock
2: {
3: public static T Stub<T>() where T : class
4: {
5: var typeOfT = typeof(T);
6: string stubName = "Stub__" + typeOfT.Name;
7: var sb = new StringBuilder();
8:
9: var methods = typeOfT
10: .GetMethods(BindingFlags.Instance | BindingFlags.Public | BindingFlags.InvokeMethod)
11: .Where(m => (m.IsVirtual || m.IsAbstract) && !m.IsSpecialName && !m.IsFinal);
12: methods.ForEach(m => sb.AppendLine(GetConfigPropertyCode(m)));
13: methods.ForEach(m => sb.AppendLine(GetMethodCode(m)));
14:
15: var scripRunner = new ScriptRunner(typeOfT);
16: var results = new Dictionary<string, object>();
17: scripRunner.AddObject<Dictionary<string, object>>("results", results);
18: scripRunner.AddUsing("CSharp5");
19: scripRunner.AddTypeCode(string.Format("public class {0} : {1} {{ {2} }}", stubName, typeOfT.FullName, sb.ToString()));
20: scripRunner.AddCode("results[\"stub\"] = new " + stubName + "();");
21: scripRunner.Run();
22:
23: return (T)results["stub"];
24: }
25:
26: private static string GetMethodCode(MethodInfo method)
27: {
28: var isProcedure = method.ReturnType == typeof(void);
29: var parameters = method.GetParameters();
30:
31: return string.Format("public {6} {0} {1} ( {2} ) {{ {3} When_{1}{5}({4}); }}",
32: isProcedure ? "void" : method.ReturnType.FullName,
33: method.Name,
34: parameters.Select(p => string.Concat(p.ParameterType.FullName, " ", p.Name)).ToStringList(),
35: isProcedure ? string.Empty : "return",
36: parameters.Select(p => p.Name).ToStringList(),
37: parameters.Any()
38: ? "_" + parameters.Select(p => p.ParameterType.Name.Replace("[]", "Array")).ToStringList("_")
39: : string.Empty,
40: method.DeclaringType.IsInterface ? "" : "override"
41: );
42: }
43:
44: private static string GetConfigPropertyCode(MethodInfo method)
45: {
46: var isProcedure = method.ReturnType == typeof(void);
47: var parameters = method.GetParameters();
48:
49: var methodReturnedType = isProcedure ? "void" : method.ReturnType.FullName;
50: var parametersType = parameters.Select(p => p.ParameterType);
51: var returnedSign = isProcedure ? "Action<{0}>" :
52: string.Format("Func<{0}{1}>", "{0}", (parametersType.Any() ? "," : "") + methodReturnedType);
53: var parametersForSign = parametersType.Select(t => t.Name.Replace("[]", "Array")).ToStringList("_");
54:
55: return string.Format("public {0} When_{1}{2} {{ get; set; }}",
56: isProcedure && !parameters.Any()
57: ? "Action"
58: : string.Format(returnedSign, parametersType.Select(t => t.FullName).ToStringList()),
59: method.Name,
60: parametersType.Any() ? "_" + parametersForSign : string.Empty);
61: }
62: }
63:
64: static class StringListExtensions
65: {
66: public static string ToStringList(this IEnumerable<string> enumerable, string separator = ", ")
67: {
68: if (!enumerable.Any())
69: return string.Empty;
70:
71: return enumerable.Aggregate((s1, s2) => string.Concat(s1, separator, s2));
72: }
73: }
74:
75: static class IEnumerableExtensions
76: {
77: public static void ForEach<T>(this IEnumerable<T> enumerable, Action<T> action)
78: {
79: foreach (var t in enumerable) action(t);
80: }
81: }