Skip to content

Instantly share code, notes, and snippets.

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

  • Save NikiforovAll/83b2cd57034abbaf53a0cb2f312eb5eb to your computer and use it in GitHub Desktop.

Select an option

Save NikiforovAll/83b2cd57034abbaf53a0cb2f312eb5eb to your computer and use it in GitHub Desktop.
StateImpl
using System;
using System.Collections.Generic;
using System.Linq;
using State;
public class Program {
public static void Main () {
var ctx = new StateClient ();
ctx.State = new StateOne (ctx);
Assert.Equal ("StateOne", ctx.State.GetType ().Name);
//Threshold is reached, lets change to StateTwo
ctx.Process ();
Assert.Equal ("StateTwo", ctx.State.GetType ().Name);
ctx.Process ();
ctx.Process ();
//Threshold is reached, lets change to StateTwo.
//Once again, rules could be defined within state (e.g. different value for threshold or something like that)
Assert.Equal ("StateOne", ctx.State.GetType ().Name);
TestRunner.Print ();
}
}
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Runtime.CompilerServices;
using System.Threading;
namespace State {
public abstract class BaseState {
public int Value { get; protected set; }
public StateClient Client { get; set; }
protected int Threshold { get; set; } = 1;
public virtual bool IsNeedToChangeState () {
return Value >= Threshold;
}
public virtual void Increment () {
Value++;
HandleContext ();
}
protected abstract void HandleContext ();
public override string ToString () {
return $"State={this.GetType().Name};Value={this.Value}";
}
}
}
namespace State {
//client class, context
public class StateClient : INotifyPropertyChanged {
public event PropertyChangedEventHandler PropertyChanged;
protected void OnPropertyChanged ([CallerMemberName] string propertyName = null) {
PropertyChanged?.Invoke (this, new PropertyChangedEventArgs (propertyName));
}
private BaseState _state;
public BaseState State {
get { return _state; }
set { SetField (ref _state, value); }
}
protected bool SetField<T> (ref T field, T value, [CallerMemberName] string propertyName = null) {
if (EqualityComparer<T>.Default.Equals (field, value))
return false;
field = value;
OnPropertyChanged (propertyName);
return true;
}
public StateClient () {
this.PropertyChanged += (sender, arg) => {
System.Console.WriteLine ($"sender={sender};arg={arg.PropertyName}");
};
}
public void Process () {
_state.Increment ();
}
}
}
namespace State {
public class StateOne : BaseState {
public StateOne (StateClient client) {
Client = client;
}
protected override void HandleContext () {
if (base.IsNeedToChangeState ()) {
Client.State = new StateTwo (this);
}
}
}
}
namespace State {
public class StateTwo : BaseState {
public StateTwo (BaseState state) {
Threshold = 3;
Value = state.Value;
Client = state.Client;
}
protected override void HandleContext () {
if (base.IsNeedToChangeState ()) {
Client.State = new StateOne (Client);
}
}
}
}
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