Skip to content

Instantly share code, notes, and snippets.

@NMillard
Created June 27, 2020 06:35
Show Gist options
  • Save NMillard/2cd48fed21e5bf3b767d4feed3dc3b3d to your computer and use it in GitHub Desktop.
Save NMillard/2cd48fed21e5bf3b767d4feed3dc3b3d to your computer and use it in GitHub Desktop.
If-Else vs Dynamic Type Discovery
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Text.Json;
namespace DesignPatterns.DynamicStrategy {
class Program {
static void Main(string[] args) {
/*
* If-else method
*/
string json = PrintOrder(Order.CreateNew(10), "Json");
string plain = PrintOrder(Order.CreateNew(10), "PlainText");
Console.WriteLine(json);
Console.WriteLine(plain);
Console.WriteLine(Environment.NewLine);
/*
* Dynamic
*/
string json2 = PrintOrder2(Order.CreateNew(10), "Json");
string plain2 = PrintOrder2(Order.CreateNew(10), "PlainText");
Console.WriteLine(json2);
Console.WriteLine(plain2);
}
/*
* If-Else Example
*/
public static string PrintOrder(Order order, string formatType) {
// Guard clauses left out for brevity
string result = string.Empty;
if (formatType == "Json") {
result = JsonSerializer.Serialize(order);
} else if (formatType == "PlainText") {
result = $"Id: {order.Id}\nSum: {order.Sum}";
} else {
result = "Unknown format";
}
return result;
}
/*
* Dynamic type discovery example
*/
private static string PrintOrder2(Order order, string formatType) {
// Dynamic type discovery process that builds a dictionary
Dictionary<string, Type> formatterTypes = Assembly
.GetExecutingAssembly()
.GetExportedTypes()
.Where(type => type.GetInterfaces().Contains(typeof(IOrderOutputStrategy)))
.ToDictionary(type => type.GetCustomAttribute<OutputFormatterName>().DisplayName);
Type chosenFormatter = formatterTypes[formatType];
// Try instantiate the formatter -- could have utilized a DI framework here instead
IOrderOutputStrategy strategy = Activator.CreateInstance(chosenFormatter) as IOrderOutputStrategy;
if (strategy is null) throw new InvalidOperationException("No valid formatter selected");
// Execute strategy method
string result = strategy.ConvertOrderToString(order);
return result;
}
}
public class Order {
private readonly string id;
private Order() {
this.id = Guid.NewGuid().ToString("D");
}
public string Id => id;
public int Sum { get; private set; }
public string GenerateOutput(IOrderOutputStrategy strategy) =>
strategy.ConvertOrderToString(this);
public static Order CreateNew(int orderSum) {
if (orderSum <= 0) throw new ArgumentException("sum must be a positive number");
var order = new Order {
Sum = orderSum,
};
return order;
}
}
[AttributeUsage(AttributeTargets.Class)]
public class OutputFormatterName : Attribute {
public OutputFormatterName(string displayName) {
DisplayName = displayName;
}
public string DisplayName { get; }
}
public interface IOrderOutputStrategy {
public string ConvertOrderToString(Order order);
}
[OutputFormatterName("Json")]
public class OrderJsonOutput : IOrderOutputStrategy {
public string ConvertOrderToString(Order order) {
string json = JsonSerializer.Serialize(order);
return json;
}
}
[OutputFormatterName("PlainText")]
public class OrderPlainTextOutput : IOrderOutputStrategy {
public string ConvertOrderToString(Order order) {
return $"Id: {order.Id}{Environment.NewLine}Sum: {order.Sum}";
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment