Skip to content

Instantly share code, notes, and snippets.

@NikiforovAll
Last active June 9, 2019 13:13
Show Gist options
  • Select an option

  • Save NikiforovAll/74dc52cef68e13bdd9314b591d39fee2 to your computer and use it in GitHub Desktop.

Select an option

Save NikiforovAll/74dc52cef68e13bdd9314b591d39fee2 to your computer and use it in GitHub Desktop.
ChainOfResponsibilityImpl
using System;
using System.Collections.Generic;
using System.Linq;
namespace ChainOfResponsibility {
/// <summary>
/// The 'Handler' abstract class
/// </summary>
public abstract class Approver {
public string Id { get; }
protected Approver successor;
protected Approver (string id) {
Id = id;
}
protected Approver () : this ("") { }
public void SetSuccessor (Approver approver) {
this.successor = approver;
}
public Approver GetSuccessor () => this.successor;
public abstract (bool, ProcessingLevel) ProcessRequest (Purchase purchase);
}
}
namespace ChainOfResponsibility {
public class ChainOfResponsibilityManager {
private Dictionary<string, string> relationshipConfig;
public ChainOfResponsibilityManager (Dictionary<string, string> relationshipConfig) {
this.relationshipConfig = relationshipConfig;
}
public Approver CreateChainOfApprovers (List<Approver> approvers) {
var configValues = relationshipConfig.Values;
Approver mainApprover = approvers.First (el => !configValues.Contains (el.Id, StringComparer.InvariantCultureIgnoreCase));
foreach (var approver in approvers) {
if (relationshipConfig.TryGetValue (approver.Id, out string currentApproverId)) {
var activeApprover = approvers.First (el => el.Id == currentApproverId);
if (activeApprover != null) {
approver.SetSuccessor (activeApprover);
}
}
}
return mainApprover;
}
}
}
namespace ChainOfResponsibility {
public class Director : Approver {
public Director (string id) : base (id) { }
public override (bool, ProcessingLevel) ProcessRequest (Purchase purchase) => purchase.Amount < 10 ? (true, ProcessingLevel.Accepted) : successor.ProcessRequest (purchase);
}
}
namespace ChainOfResponsibility {
public class President : Approver {
public President (string id) : base (id) { }
public override (bool, ProcessingLevel) ProcessRequest (Purchase purchase) => purchase.Amount < 20 ? (true, ProcessingLevel.EscalationLevelTwo) : (false, ProcessingLevel.Rejected);
}
}
namespace ChainOfResponsibility {
public enum ProcessingLevel {
Accepted,
EscalationLevelOne,
EscalationLevelTwo,
Rejected
}
}
namespace ChainOfResponsibility {
public struct Purchase {
public Purchase (double amount, int number, string description) {
Amount = amount;
Number = number;
Description = description;
}
public double Amount { get; }
public int Number { get; }
public string Description { get; }
public static explicit operator Purchase ((double, int, string) tuple) {
return new Purchase (tuple.Item1, tuple.Item2, tuple.Item3);
}
}
}
namespace ChainOfResponsibility {
public class VicePresident : Approver {
public VicePresident (string id) : base (id) { }
public override (bool, ProcessingLevel) ProcessRequest (Purchase purchase) => purchase.Amount < 15 ? (true, ProcessingLevel.EscalationLevelOne) : successor.ProcessRequest (purchase);
}
}
using System;
using System.Collections.Generic;
using System.Linq;
using ChainOfResponsibility;
public class Program {
public static void Main () {
List<Approver> approvers = new List<Approver> {
new Director ("#1"),
new VicePresident ("#2"),
new President ("#3")
};
ChainOfResponsibilityManager manager = new ChainOfResponsibilityManager (
new Dictionary<string, string> {
["#1"] = "#2",
["#2"] = "#3"
}
);
var baseApprover = manager.CreateChainOfApprovers (approvers);
Purchase purchase1 = (Purchase) (5.0, 1, "p1");
Purchase purchase2 = (Purchase) (11.0, 1, "p1");
Purchase purchase3 = (Purchase) (16.0, 1, "p1");
Purchase purchase4 = (Purchase) (21.0, 1, "p1");
var result1 = approvers[0].ProcessRequest (purchase1);
Assert.Equal (ProcessingLevel.Accepted, result1.Item2);
var result2 = approvers[0].ProcessRequest (purchase2);
Assert.Equal (ProcessingLevel.EscalationLevelOne, result2.Item2);
var result3 = approvers[0].ProcessRequest (purchase3);
Assert.Equal (ProcessingLevel.EscalationLevelTwo, result3.Item2);
var result4 = approvers[0].ProcessRequest (purchase4);
Assert.Equal (false, result4.Item1);
Assert.Equal (ProcessingLevel.Rejected, result4.Item2);
TestRunner.Print ();
}
}
using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.CompilerServices;
public static class Assert {
public static void Equal<T> (T a, T b, [CallerMemberName] string callerName = "", [CallerLineNumber] int callerLine = 0) {
if (!a.Equals (b)) {
// throw new Exception ($"{a} doesn't equal to {b}");
TestRunner.AddResult (
new TestRunResult () {
CallerName = callerName,
CallerLine = callerLine.ToString (),
Success = false,
Assertion = "Equal<T>",
ErrorMessage = $"{a} doesn't equal to {b}"
});
} else {
TestRunner.AddResult (
new TestRunResult () {
CallerName = callerName,
CallerLine = callerLine.ToString (),
Success = true,
Assertion = "Single<T>"
});
}
}
public static void Equal<T> (IEnumerable<T> a,
IEnumerable<T> b, [CallerMemberName] string callerName = "", [CallerLineNumber] int callerLine = 0) {
if (a.Count () != b.Count ()) {
TestRunner.AddResult (
new TestRunResult () {
CallerName = callerName,
CallerLine = callerLine.ToString (),
Success = false,
Assertion = "Equal<T>",
ErrorMessage = $"a.{a.Count()} != b.{b.Count()}"
});
} else if (!a.SequenceEqual (b)) {
TestRunner.AddResult (
new TestRunResult () {
CallerName = callerName,
CallerLine = callerLine.ToString (),
Success = false,
Assertion = "SequenceEqual<T>",
ErrorMessage = $"Different sequences"
});
} else {
TestRunner.AddResult (
new TestRunResult () {
CallerName = callerName,
CallerLine = callerLine.ToString (),
Success = true,
Assertion = "Equal<T>"
});
}
}
public static void Single<T> (IEnumerable<T> collection, [CallerMemberName] string callerName = "", [CallerLineNumber] int callerLine = 0) {
if (collection.Count () != 1) {
// throw new Exception ("Collection doesn't contain 1 element");
TestRunner.AddResult (
new TestRunResult () {
CallerName = callerName,
CallerLine = callerLine.ToString (),
Success = false,
Assertion = "Single<T>",
ErrorMessage = "Collection doesn't contain 1 element"
});
}
TestRunner.AddResult (
new TestRunResult () {
CallerName = callerName,
CallerLine = callerLine.ToString (),
Success = true,
Assertion = "Single<T>"
});
}
public static void Contains<T> (T token1, T token2, [CallerMemberName] string callerName = "", [CallerLineNumber] int callerLine = 0) {
if (typeof (T) == typeof (System.String)) {
if (!((token2 as string)).Contains (token1 as string)) {
// throw new Exception ($"{token2} doesn't contain {token1}");
TestRunner.AddResult (
new TestRunResult () {
CallerName = callerName,
CallerLine = callerLine.ToString (),
Success = false,
Assertion = "Contains<T>",
ErrorMessage = $"{token2} doesn't contain {token1}"
});
} else {
TestRunner.AddResult (
new TestRunResult () {
CallerName = callerName,
CallerLine = callerLine.ToString (),
Success = true,
Assertion = "Contains<T>"
});
}
} else {
throw new Exception ("It is not possible to use .Contains() method");
}
}
public static void All<T> (IEnumerable<T> collection, Func<T, bool> predicate, [CallerMemberName] string callerName = "", [CallerLineNumber] int callerLine = 0) {
bool res = collection.All (predicate);
var tr = new TestRunResult () {
CallerName = callerName,
CallerLine = callerLine.ToString (),
Success = res,
Assertion = "All<T>"
};
TestRunner.AddResult (tr);
if(!res) {
tr.ErrorMessage = "Condition is not met for all members";
}
}
}
public static class TestRunner {
public static List<TestRunResult> Results { get; } = new List<TestRunResult> ();
public static void AddResult (TestRunResult res) {
Results.Add (res);
}
public static void Print () {
System.Console.WriteLine ("TestRunner.Print");
System.Console.WriteLine ("============================================");
foreach (var log in Results) {
System.Console.WriteLine (log);
}
System.Console.WriteLine ("============================================");
}
}
public class TestRunResult {
public string CallerName { get; set; }
public string CallerLine { get; set; }
public string Assertion { get; set; }
public bool Success { get; set; }
public string ErrorMessage { get; set; }
public override string ToString () {
return $"Assertion: {Assertion, 15}; MethodName: {CallerName, 10}; Line: {CallerLine, 3}; " + (Success? $"Success: {Success}": $"ErrorMessage: {ErrorMessage}");
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment