-
-
Save peterhoang/1cf52c0a09f59217cb26435120496ed7 to your computer and use it in GitHub Desktop.
If-Else vs Dynamic Type Discovery
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.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
Example of Strategy Pattern. Also, dynamically find class implementation via Reflection.