Last active
August 29, 2015 14:11
-
-
Save joeriks/431f3bb234ffc79d5100 to your computer and use it in GitHub Desktop.
fun with delegates, expressive namings, pipe forwards, func di and auto-method-name-logging in C#
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using System; | |
using System.Reflection; | |
public class Program | |
{ | |
static void Main(string[] args) | |
{ | |
// setup db and logger using funcs | |
// use default | |
contextfuncs.db = contextfuncs.default_database; | |
// set verbose to true to demonstrate | |
// explicit logging with method names and results | |
contextfuncs.logger = new Func<logger>(() => new logger { verbose = true }); | |
// pipe the commands | |
// use expressive naming | |
// but avoid keeping each result in a separate var | |
"Give me a product id please" | |
.IntoExpr(command_line_operations.ask_user_for_integer) | |
.IntoExpr(query_the_database.products.with_id) | |
.IntoExpr(format_strings.product_formatted_for_commandline) | |
.IntoExpr(command_line_operations.write_message_to_user_and_wait_for_enter); | |
} | |
} | |
public static class contextfuncs | |
{ | |
public static Func<database> default_database = new Func<database>(() => new database()); | |
public static Func<logger> default_logger = new Func<logger>(() => new logger()); | |
public static Func<database> db { get; set; } | |
public static Func<logger> logger { get; set; } | |
} | |
public class database { } | |
public class logger | |
{ | |
public bool verbose { get; set; } | |
public void log(bool isverbose, Func<string> logmessageFunc) | |
{ | |
if (isverbose == verbose || !isverbose) | |
{ | |
var logmessage = logmessageFunc(); | |
var color = Console.ForegroundColor; | |
Console.ForegroundColor = ConsoleColor.DarkCyan; | |
Console.WriteLine(DateTime.Now.ToLongTimeString() + "> " + logmessage); | |
Console.ForegroundColor = color; | |
} | |
} | |
} | |
public class context | |
{ | |
public database database { get; set; } | |
public logger logger { get; set; } | |
} | |
public static class command_line_operations | |
{ | |
public static int ask_user_for_integer(string ask_user) | |
{ | |
Console.WriteLine(ask_user); | |
var input = Console.ReadLine(); | |
return Int32.Parse(input); | |
} | |
public static void wait_for_enter() | |
{ | |
Console.ReadLine(); | |
} | |
public static string write_message_to_user_and_wait_for_enter(format_strings.string_formatted_for_commandline message) | |
{ | |
Console.WriteLine(message); | |
return Console.ReadLine(); | |
} | |
} | |
public static class format_strings | |
{ | |
public class string_formatted_for_commandline | |
{ | |
public string message { get; set; } | |
public override string ToString() | |
{ | |
return message.ToString(); | |
} | |
public string_formatted_for_commandline(string message) | |
{ | |
this.message = message; | |
} | |
} | |
public static string_formatted_for_commandline product_formatted_for_commandline(Product p) | |
{ | |
return new string_formatted_for_commandline(String.Format("Product name: '{0}' Id: {1}", p.Name, p.Id)); | |
} | |
} | |
public class Product | |
{ | |
public int Id { get; set; } | |
public string Name { get; set; } | |
} | |
public static class query_the_database | |
{ | |
public static void assert_the_database_is_available() | |
{ | |
if (contextfuncs.db == null || contextfuncs.db() == null) throw new Exception("Db error"); | |
} | |
public static class products | |
{ | |
public static Product with_id(int id) | |
{ | |
assert_the_database_is_available(); | |
return new Product { Id = id, Name = "Some name" }; | |
} | |
} | |
} | |
public static class IntoExtensions | |
{ | |
public delegate TOut MethodDelegate<TIn, TOut>(TIn obj); | |
public delegate void MethodDelegate<TIn>(TIn obj); | |
public delegate void MethodDelegate(); | |
public static string method_info(MethodInfo methodInfo) | |
{ | |
return methodInfo.DeclaringType.FullName + "." + methodInfo.Name; | |
} | |
public static TOut IntoExpr<TIn, TOut>(this TIn obj, MethodDelegate<TIn, TOut> del) | |
{ | |
var result = del(obj); | |
contextfuncs.logger().log(true, () => String.Format("{0}({1}): {2}", method_info(del.Method), obj.ToString(), result.ToString())); | |
return result; | |
} | |
public static void IntoExpr<TIn>(this TIn obj, MethodDelegate<TIn> del) | |
{ | |
del(obj); | |
contextfuncs.logger().log(true, () => String.Format("{0}({1}): void", method_info(del.Method), obj.ToString())); | |
} | |
public static void IntoExpr<TIn>(this TIn obj, MethodDelegate del) | |
{ | |
del(); | |
contextfuncs.logger().log(true, () => String.Format("{0}(): void", method_info(del.Method))); | |
} | |
public static TOut Into<TIn, TOut>(this TIn obj, Func<TIn, TOut> f) | |
{ return f(obj); } | |
public static T Passthrough<T>(this T obj) | |
{ | |
return obj; | |
} | |
public static T PassthroughAssert<T>(this T obj, bool condition) | |
{ | |
if (condition) return obj; | |
throw new Exception("Condition not met"); | |
} | |
public static void Into<TIn>(this TIn obj, Action<TIn> f) | |
{ f(obj); } | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment