using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.Diagnostics.CodeAnalysis;
using System.Linq.Expressions;
using System.Runtime.CompilerServices;
using System.Runtime.Serialization.Formatters.Binary;
using System.Runtime.InteropServices;
using System.Text.RegularExpressions;
using System.Threading.Tasks;
using Microsoft.Extensions.DependencyInjection;
using static System.Console;
using static Utilities.DebugMethods;
public static void Main()
string[] words = { "Bugs Bunny", "Daffy Duck", "Mickey Mouse", "Foghorn Leghorn" };
var u=new UnitOfWork(logger:new ConsoleLogger());
var sss=u.XForEvery<string,string>(words,r=>r.ToUpper());
var logType=LogType.Error | LogType.Information;
var chain=new ChainOfWorkFunctions(new ConsoleLogger(), isTimed:true);
bool CheckFlag<T>(T enumValue, T enumVariable) where T : System.Enum
=>(Convert.ToByte(enumVariable) & Convert.ToByte(enumValue)) ==Convert.ToByte(enumValue);
chain.AddMethod(r=>(int)r+1);
chain.AddMethod(r=>r.ToInt32()+111);
chain.AddMethod(r=>r+"Lee");
chain.AddMethod(r=>r.ToString().ToUpper());
chain.BeforeExecute+= (sender,args)=>WL("before chain EXE - " + args.Data.Elapsed.ToString());
chain.AfterExecute+=(sender,args)=>WL("after chain EXE - " + args.Data.Elapsed.ToString());
chain.BeforeLinkExecute+=(sender,args)=>WL("before link exe - " + args.Data.Elapsed.ToString());
chain.AfterLinkExecute+=(sender,args)=>WL("After Link exe - " + args.Data.Elapsed.ToString());
WL(chain.Execute<string>(1));
var v=ValueTuple.Create(1,2);
int vv=((ValueTuple<int,int>)(3,4)).Item1;
words.Execute<string[]>(Action: (r)=>WL(">>>" + r[1]), logger:new ConsoleLogger(), isTimed: true, useTryCatch: true, rethrowExceptions: true );
using(var UoW=new UnitOfWork(logger:new ConsoleLogger()))
UoW.BeforeExecute+= (sender,args)=>WL("before EXE - " + args.Data.Elapsed.ToString());
UoW.BeforeExecute+= (s,a)=>WL("before EXE2");
UoW.AfterExecute+=(sender,args)=>WL("after EXE - " + ((UnitOfWork)sender).Elapsed.ToString());
UoW.BeforeDispose+=(s,a)=>WL("before DISPOSE");
public partial class UnitOfWork
public IEnumerable<OUT> XForEvery<IN,OUT>([DisallowNull] IEnumerable<IN> inputs, [DisallowNull] Expression<Func<IN,OUT>> function)
=> XForEvery<IN,OUT>(function, inputs as IN[]);
public IEnumerable<OUT> XForEvery<IN,OUT>([DisallowNull] IEnumerable<Expression<Func<IN,OUT>>> functions, [DisallowNull] IN input)
=> XForEvery<IN,OUT>(input,functions as Expression<Func<IN,OUT>>[]);
public IEnumerable<OUT> XForEvery<IN,OUT>([DisallowNull] IN input, [DisallowNull] params Expression<Func<IN,OUT>> [] functions)
=> (from function in functions select Execute<IN,OUT>(input,function)).ToList();
public IEnumerable<OUT> XForEvery<IN,OUT>([DisallowNull] Expression<Func<IN,OUT>> function, [DisallowNull] params IN [] inputs)
=> (from input in inputs select Execute<IN,OUT>(input,function)).ToList();
public IEnumerable<(TID functionID, IN input, OUT result)> XForEvery<TID,IN,OUT>(IEnumerable<IN> inputs, params (TID functionID, Func<IN,OUT> function) [] functions)
select f.functionID,input=i, result=f.function(input)
return default(IEnumerable<(TID key, IN input, OUT result)>);
public IEnumerable<OUT> PXForEvery<IN,OUT>([DisallowNull] IEnumerable<IN> inputs, [DisallowNull] Expression<Func<IN,OUT>> function)
=> PXForEvery<IN,OUT>(function,inputs as IN[]);
public IEnumerable<OUT> PXForEvery<IN,OUT>([DisallowNull] IEnumerable<Expression<Func<IN,OUT>>> functions, [DisallowNull] IN input)
=> PXForEvery<IN,OUT>(input,functions as Expression<Func<IN,OUT>>[]);
public IEnumerable<OUT> PXForEvery<IN,OUT>([DisallowNull] IN input, [DisallowNull] params Expression<Func<IN,OUT>> [] functions)
=> (from function in functions.AsParallel() select Execute<IN,OUT>(input,function)).ToList();
public IEnumerable<OUT> PXForEvery<IN,OUT>([DisallowNull] Expression<Func<IN,OUT>> function, [DisallowNull] params IN [] inputs)
=> (from input in inputs.AsParallel() select Execute<IN,OUT>(input,function)).ToList();
public void XecuteForAll<IN>([DisallowNull] IEnumerable<IN> inputs, [DisallowNull] Expression<Action<IN>> action )
=> XecuteForAll<IN>(action, inputs as IN[]);
public void XecuteForAll<IN>([DisallowNull] IEnumerable<Expression<Action<IN>>> actions, [DisallowNull] IN input )
=> XecuteForAll<IN>(input, actions as Expression<Action<IN>>[]);
public void XecuteForAll<IN>([DisallowNull] IN input, [DisallowNull] params Expression<Action<IN>> [] actions)
=> actions.ToList().ForEach(action=>Execute<IN>(input, action));
public void XecuteForAll<IN>([DisallowNull] Expression<Action<IN>> action, [DisallowNull] params IN [] inputs)
=> inputs.ToList().ForEach(input=>Execute<IN>(input, action));
public void PXecuteForAll<IN>([DisallowNull] IEnumerable<IN> inputs, [DisallowNull] Expression<Action<IN>> action)
=> PXecuteForAll<IN>(action,inputs as IN[]);
public void PXecuteForAll<IN>([DisallowNull] IEnumerable<Expression<Action<IN>>> actions, [DisallowNull] IN input)
=> PXecuteForAll<IN>(input, actions as Expression<Action<IN>>[]);
public void PXecuteForAll<IN>([DisallowNull] IN input, [DisallowNull] params Expression<Action<IN>> [] actions)
=> actions.AsParallel().ForAll(action=>Execute<IN>(input, action));
public void PXecuteForAll<IN>([DisallowNull] Expression<Action<IN>> action, [DisallowNull] params IN [] inputs)
=> inputs.AsParallel().ForAll(input=>Execute<IN>(input, action));
public partial class UnitOfWork : WorkBase
private const string executeSourceMask=$"{nameof(UnitOfWork)}-{nameof(Execute)}";
public UnitOfWork() : base() {}
public UnitOfWork(ILogger logger) : base(logger) {}
public UnitOfWork(ILogger logger, bool isTimed=true, bool useTryCatch=true, bool rethrowExceptions=true)
: base(logger, isTimed, useTryCatch, rethrowExceptions) {}
private void Log(LogType logType, string methodName = $"{executeSourceMask}", Exception e=null)
(logType==LogType.Error).Then( ()=>logger?.WriteError($"{methodName}", $"{methodName} - Error: {e.Message}") );
(logType==LogType.Information).Then( ()=>logger?.WriteInfo(methodName,
string.Concat($"{methodName} ran at {System.DateTime.Now.ToUniversalTime()}",
IsTimed ? $" in {((decimal)Elapsed.Ticks/10000m)} ms ({Elapsed.Ticks} ticks)" : "")) );
public OUT Execute<IN, OUT>([DisallowNull] IN input, [DisallowNull] Expression<Func<IN,OUT>> method, string methodName = $"{executeSourceMask}")
try { Prepare(); BeforeRun(); Run(); AfterRun(); LogInfo(); }
catch (Exception e) { LogError(e); if (RethrowExceptions) throw; }
else { Prepare(); BeforeRun(); Run(); AfterRun(); LogInfo(); End(); }
void Prepare() => (methodName, Input, Elapsed)=(string.IsNullOrWhiteSpace(methodName) ? $"{executeSourceMask}" : methodName, input, TimeSpan.Zero);
void BeforeRun() { PreExecute(); RaiseBeforeExecuteEvent(this); }
void Run() => (result, Elapsed)=IsTimed ? input.TimedFunction(i=>method.Compile()(i)) : ( method.Compile()(input), Elapsed );
void AfterRun() { Input=input; PostExecute(); RaiseAfterExecuteEvent(this); }
void LogInfo() => Log(LogType.Information, methodName);
void LogError(Exception e) => Log(LogType.Error,methodName,e);
public async Task<OUT> ExecuteAsync<IN, OUT>([DisallowNull] IN input, [DisallowNull] Expression<Func<IN,OUT>> method, string methodName = $"{executeSourceMask}")
=> await Task<OUT>.Run(()=>Execute<IN,OUT>(input, method, methodName));
public void Execute<IN>([DisallowNull] IN input, [DisallowNull] Expression<Action<IN>> method, string methodName = $"{executeSourceMask}")
var elapsed = Elapsed = TimeSpan.Zero;
try { Prepare(); BeforeRun(); Run(); AfterRun(); LogInfo(); }
catch (Exception e) { LogError(e); if (RethrowExceptions) throw; }
else { Prepare(); BeforeRun(); Run(); AfterRun(); LogInfo(); End(); }
void Prepare() => (methodName, Input)=(string.IsNullOrWhiteSpace(methodName) ? $"{executeSourceMask}" : methodName, input);
void BeforeRun() { PreExecute(); RaiseBeforeExecuteEvent(this); }
void Run() => input.IfThenElse(IsTimed, i=>input.TimedAction(i2=>method.Compile()(i2),out elapsed), i=>method.Compile()(i));
void AfterRun() { Elapsed=elapsed; PostExecute(); RaiseAfterExecuteEvent(this); }
void LogInfo() => Log(LogType.Information, methodName);
void LogError(Exception e) => Log(LogType.Error, methodName, e);
public async Task ExecuteAsync<IN>([DisallowNull] IN input, [DisallowNull] Expression<Action<IN>> method, string methodName = $"{executeSourceMask}")
=> await Task.Run(()=>Execute(input, method, methodName));
partial void PreExecute();
partial void PostExecute();
public class ChainOfWorkFunctions : ChainOfWork<Func<object,object>>
public ChainOfWorkFunctions() : base() {}
public ChainOfWorkFunctions(ILogger logger) : base(logger) {}
public ChainOfWorkFunctions(ILogger logger, bool isTimed=true, bool useTryCatch=true, bool rethrowExceptions=true)
: base(logger, isTimed, useTryCatch, rethrowExceptions) {}
public class ChainOfWorkActions : ChainOfWork<Action<object>>
public ChainOfWorkActions() : base() {}
public ChainOfWorkActions(ILogger logger) : base(logger) {}
public ChainOfWorkActions(ILogger logger, bool isTimed=true, bool useTryCatch=true, bool rethrowExceptions=true)
: base(logger, isTimed, useTryCatch, rethrowExceptions) {}
public partial class ChainOfWork<TActionOrFunc> : WorkBase, IEnumerable<Expression<TActionOrFunc>>
private const string executeSourceMask=$"{nameof(ChainOfWork<TActionOrFunc>)}-{nameof(Execute)} ";
private List<Expression<TActionOrFunc>> methods {get;set;}=new List<Expression<TActionOrFunc>>();
public event EventHandler<WorkerEventArgs<WorkBase>> onBeforeLinkExecute;
public event EventHandler<WorkerEventArgs<WorkBase>> onAfterLinkExecute;
public ChainOfWork() : base() {}
public ChainOfWork(ILogger logger) : base(logger) {}
public ChainOfWork(ILogger logger, bool isTimed=true, bool useTryCatch=true, bool rethrowExceptions=true)
: base(logger, isTimed, useTryCatch, rethrowExceptions) {}
public TEnd Execute<TEnd>([DisallowNull] object input)
(TEnd result, Elapsed)=IsTimed ?
input.TimedFunction(r=>execute<TEnd>(r)) : (execute<TEnd>(input), Elapsed);
public TEnd Execute<TEnd>([DisallowNull] object input, [DisallowNull] params Expression<TActionOrFunc> [] functions)
return Execute<TEnd>(input);
private TEnd execute<TEnd>(object input)
(object result, int c, DateTime start, Input)=(null, 1, DateTime.UtcNow, input); UnitOfWork UoW;
BeforeRun(); Run(); AfterRun(); Log();
return (TEnd)Convert.ChangeType(result,typeof(TEnd));
void BeforeRun() { PreExecute(); RaiseBeforeExecuteEvent(this); }
using(UoW=new UnitOfWork(logger:logger, isTimed:IsTimed, useTryCatch:UseTryCatch, rethrowExceptions:RethrowExceptions))
foreach(Expression<TActionOrFunc> method in methods)
onBeforeLinkExecute?.Invoke(this,new WorkerEventArgs<WorkBase>{Data=this,debug=c.ToString()});
if(method is Expression<Func<object,object>> f) RunFunction(f);
else if (method is Expression<Action<object>> a) RunAction(a);
else throw new ArgumentException("Action or Func MUST be specified.");
(Input, Elapsed)=(UoW.Input, UoW.Elapsed);
onAfterLinkExecute?.Invoke(this,new WorkerEventArgs<WorkBase>{Data=this,debug=(c-1).ToString()});
void RunFunction(Expression<Func<object,object>> f)
=> result=UoW.Execute<object,object>(input:(result==null ? input : result), method:f, methodName:$"{executeSourceMask}#{c++}");
void RunAction(Expression<Action<object>> a)
=> UoW.Execute<object>(input:(result==null ? input : result), method:a, methodName:$"{executeSourceMask}#{c++}");;
void AfterRun() { Elapsed=DateTime.UtcNow-start; PostExecute(); RaiseAfterExecuteEvent(this); }
logger?.WriteInfo($"{nameof(ChainOfWork<TActionOrFunc>)} - SUMMARY ",
string.Concat($"{executeSourceMask}ran at {System.DateTime.Now.ToUniversalTime()}",
IsTimed ? $" in {((decimal)Elapsed.Ticks/10000m)} ms ({Elapsed.Ticks} ticks)" : ""));
public void AddMethod([DisallowNull] Expression<TActionOrFunc> @methods) => this.methods.Add(@methods);
public void AddMethods([DisallowNull] params Expression<TActionOrFunc> [] @methods) => this.methods.AddRange(@methods);
public IEnumerator<Expression<TActionOrFunc>> GetEnumerator() => this.methods.GetEnumerator();
IEnumerator IEnumerable.GetEnumerator() => this.GetEnumerator();
#region Thread Synchronized
public event EventHandler<WorkerEventArgs<WorkBase>> BeforeLinkExecute
[MethodImpl(MethodImplOptions.Synchronized)] add => onBeforeLinkExecute=(EventHandler<WorkerEventArgs<WorkBase>>)Delegate.Combine(onBeforeLinkExecute,value);
[MethodImpl(MethodImplOptions.Synchronized)] remove => onBeforeLinkExecute=(EventHandler<WorkerEventArgs<WorkBase>>)Delegate.Remove(onBeforeLinkExecute,value);
public event EventHandler<WorkerEventArgs<WorkBase>> AfterLinkExecute
[MethodImpl(MethodImplOptions.Synchronized)] add => onAfterLinkExecute=(EventHandler<WorkerEventArgs<WorkBase>>)Delegate.Combine(onAfterLinkExecute,value);
[MethodImpl(MethodImplOptions.Synchronized)] remove => onAfterLinkExecute=(EventHandler<WorkerEventArgs<WorkBase>>)Delegate.Remove(onAfterLinkExecute,value);
#endregion Thread Synchronized
partial void PreExecute();
partial void PostExecute();
public abstract class WorkBase : System.IDisposable
protected ILogger logger {get;set;}
public dynamic Input {get;protected set;}
public TimeSpan Elapsed {get;protected set;}
public bool IsTimed {get;set;}=true;
public bool UseTryCatch {get;set;}=true;
public bool RethrowExceptions {get;set;}=true;
protected bool IsAuthenticated {get;set;}=false;
protected bool IsAuthorized {get;set;}=false;
public WorkBase() => SetParameters();
public WorkBase(ILogger logger) => SetParameters(logger);
public WorkBase(ILogger logger, bool isTimed=true, bool useTryCatch=true, bool rethrowExceptions=true)
=> SetParameters(logger, isTimed, useTryCatch, rethrowExceptions);
protected void SetParameters(ILogger logger=null, bool isTimed=true, bool useTryCatch=true, bool rethrowExceptions=true)
=> (this.logger, IsTimed, UseTryCatch, RethrowExceptions)=(logger, isTimed, useTryCatch, rethrowExceptions);
public (bool IsAllowed, string CorrelationID) Authenticate(params SecureString [] credentials)
=> (IsAllowed:true, CorrelationID:DateTime.Now.ToUniversalTime().Ticks.ToString());
public (bool IsAllowed, string CorrelationID) Authorize(params SecureString [] credentials)
=> (IsAllowed:true, CorrelationID:DateTime.Now.ToUniversalTime().Ticks.ToString());
private event EventHandler<WorkerEventArgs<WorkBase>> onBeforeExecute;
private event EventHandler<WorkerEventArgs<WorkBase>> onAfterExecute;
private event EventHandler<WorkerEventArgs<WorkBase>> onBeforeDispose;
#region Thread Synchronized
public event EventHandler<WorkerEventArgs<WorkBase>> BeforeExecute
[MethodImpl(MethodImplOptions.Synchronized)] add => onBeforeExecute=(EventHandler<WorkerEventArgs<WorkBase>>)Delegate.Combine(onBeforeExecute,value);
[MethodImpl(MethodImplOptions.Synchronized)] remove => onBeforeExecute=(EventHandler<WorkerEventArgs<WorkBase>>)Delegate.Remove(onBeforeExecute,value);
public event EventHandler<WorkerEventArgs<WorkBase>> AfterExecute
[MethodImpl(MethodImplOptions.Synchronized)] add => onAfterExecute=(EventHandler<WorkerEventArgs<WorkBase>>)Delegate.Combine(onAfterExecute,value);
[MethodImpl(MethodImplOptions.Synchronized)] remove => onAfterExecute=(EventHandler<WorkerEventArgs<WorkBase>>)Delegate.Remove(onAfterExecute,value);
public event EventHandler<WorkerEventArgs<WorkBase>> BeforeDispose
[MethodImpl(MethodImplOptions.Synchronized)] add => onBeforeDispose=(EventHandler<WorkerEventArgs<WorkBase>>)Delegate.Combine(onBeforeDispose,value);
[MethodImpl(MethodImplOptions.Synchronized)] remove => onBeforeDispose=(EventHandler<WorkerEventArgs<WorkBase>>)Delegate.Remove(onBeforeDispose,value);
#endregion Thread Synchronized
protected virtual void RaiseBeforeExecuteEvent(WorkBase sender) => onBeforeExecute?.Invoke(sender,new WorkerEventArgs<WorkBase>{Data=this});
protected virtual void RaiseAfterExecuteEvent(WorkBase sender) => onAfterExecute?.Invoke(sender,new WorkerEventArgs<WorkBase>{Data=this});
protected virtual void RaiseBeforeDisposeEvent(WorkBase sender) => onBeforeDispose?.Invoke(sender,new WorkerEventArgs<WorkBase>{Data=this});
public bool disposed=false;
public virtual void Dispose()
Dispose(disposing: true);
GC.SuppressFinalize(this);
protected virtual void Dispose(bool disposing)
RaiseBeforeDisposeEvent(this);
public class WorkerEventArgs<T> : EventArgs
public string debug {get;set;}
public static class UnitOfWorkExtenders
private const string executeSourceMask=$"{nameof(UnitOfWork)}-{nameof(Execute)}";
public static OUT Execute<IN, OUT>([DisallowNull] this IN input, [DisallowNull] Expression<Func<IN,OUT>> Function,
string methodName = $"{executeSourceMask}", ILogger logger = null, bool isTimed = false, bool useTryCatch = true, bool rethrowExceptions = true)
(OUT result, TimeSpan elapsed) local=(default(OUT),new TimeSpan());
try { Prepare(); Run(); Log(); }
catch ( Exception e) { LogError(e); if (rethrowExceptions) throw; }
else { Prepare(); Run(); Log(); End(); }
void Prepare() => methodName=string.IsNullOrWhiteSpace(methodName) ? null : methodName;
void Run() => local=isTimed ? input.TimedFunction(i=>Function.Compile()(i)) : ( Function.Compile()(input), local.elapsed );
logger?.WriteInfo(methodName ?? $"{executeSourceMask}",
string.Concat($"{methodName??executeSourceMask} ran at {System.DateTime.Now.ToUniversalTime()}",
isTimed ? $" in {((decimal)local.elapsed.Ticks/10000m)} ms ({local.elapsed.Ticks} ticks)" : "") );
void LogError(Exception e) => logger?.WriteError(methodName ?? $"{executeSourceMask}", $"{methodName??Function.Name} - Error: {e.Message}");
public static async Task<OUT> ExecuteAsync<IN, OUT>([DisallowNull] this IN input, [DisallowNull] Expression<Func<IN,OUT>> method, string methodName = $"{executeSourceMask}")
=> await Task<OUT>.Run(()=>Execute(input, method, methodName));
public static void Execute<IN>(
[DisallowNull] this IN input, [DisallowNull] Expression<Action<IN>> Action,
string methodName = $"{executeSourceMask}", ILogger logger = null, bool isTimed=false, bool useTryCatch = true, bool rethrowExceptions = true)
TimeSpan elapsed=new TimeSpan();
try { Prepare(); Run(); Log(); }
catch (Exception e) { LogError(e); if (rethrowExceptions) throw; }
else { Prepare(); Run(); Log(); End(); }
void Prepare() => methodName=string.IsNullOrWhiteSpace(methodName) ? null : methodName;
void Run() => input.IfThenElse(isTimed, i=>i.TimedAction(i2=>Action.Compile()(i2),out elapsed), i=>Action.Compile()(i));
logger?.WriteInfo(methodName ?? $"{executeSourceMask}",
string.Concat($"{methodName??executeSourceMask} ran at {DateTime.Now.ToUniversalTime()}",
isTimed ? $" in {((decimal)elapsed.Ticks/10000m)} ms ({elapsed.Ticks} ticks)" : ""));
void LogError(Exception e) => logger?.WriteError(methodName ?? $"{executeSourceMask}", $"{methodName??Action.Name} - Error: {e.Message}");
public static async Task ExecuteAsync<IN>([DisallowNull] this IN input, [DisallowNull] Expression<Action<IN>> method, string methodName = $"{executeSourceMask}")
=> await Task.Run(()=>Execute(input, method, methodName));
namespace ExtensionMethods
public static class Extenders
public static OUT X<IN,OUT>([DisallowNull] this IN toThat, [DisallowNull] Func<IN,OUT> doThis) => doThis(toThat);
public static void X<IN>([DisallowNull] this IN toThat, [DisallowNull] Action<IN> doThis) => doThis(toThat);
public static OUT With<IN,OUT>([DisallowNull] this IN toThat, [DisallowNull] Func<IN,OUT> doThis) => doThis(toThat);
public static void With<IN>([DisallowNull] this IN toThat, [DisallowNull] Action<IN> doThis) => doThis(toThat);
public static OUT Using<IN, OUT>([DisallowNull] this IN toUse, [DisallowNull] Func<IN,OUT> function=null, bool suppressFinalize=true)
var result=function(toUse);
if(toUse is IDisposable d)
if(suppressFinalize) System.GC.SuppressFinalize(toUse);
public static void Using<IN>([DisallowNull] this IN toUse, [DisallowNull] Action<IN> action, bool suppressFinalize=true) where IN : IDisposable
if(suppressFinalize) System.GC.SuppressFinalize(toUse);
public static TimeSpan TimedAction<T>([DisallowNull] this T input, [DisallowNull] Expression<Action<T>> action)
var start=DateTime.UtcNow;
return DateTime.UtcNow-start;
public static void TimedAction<T>([DisallowNull] this T input, [DisallowNull] Expression<Action<T>> action, out TimeSpan interval)
{ interval=TimedAction(input, action); return; }
public static (TResult Result, TimeSpan Elapsed) TimedFunction<T,TResult>([DisallowNull] this T input, [DisallowNull] Expression<Func<T,TResult>> function)
TResult result=TimedFunction<T,TResult>(input, function, out TimeSpan Elapsed) ?? default(TResult);
return (result, Elapsed);
public static TResult TimedFunction<T,TResult>([DisallowNull] this T input, [DisallowNull] Expression<Func<T,TResult>> function, out TimeSpan interval)
var start=DateTime.UtcNow;
TResult result=function.Compile()(input) ?? default(TResult);
interval=DateTime.UtcNow-start;
public static void IfThenElse<T>([DisallowNull] this T input, bool condition, [DisallowNull] Expression<Action<T>> actionTrue, [DisallowNull] Expression<Action<T>> actionFalse)
{ if(condition) actionTrue.Compile()(input); else actionFalse.Compile()(input); }
public static void Then([DisallowNull] this bool condition, [DisallowNull] Action action)
{ if(condition) action(); }
public static T ChangeType<T>([DisallowNull] this object val)
=> (T)Convert.ChangeType(val,typeof(T));
public static T Coalesce<T>([DisallowNull] this bool NotCondition, params T [] toCheck)
{ foreach(var item in toCheck) {if(!NotCondition) return item; } return default(T); }
public static Int32 ToInt32(this object o) => Convert.ToInt32(o);
public static T DeepCopyReflection<T>(this T input)
var type = input.GetType();
T clonedObj = (T)Activator.CreateInstance(type);
foreach (var property in type.GetProperties().Where(p=>p.CanWrite))
object value = property.GetValue(input);
if (value != null && value.GetType().IsClass && !value.GetType().FullName.StartsWith("System."))
property.SetValue(clonedObj, DeepCopyReflection(value));
property.SetValue(clonedObj, value);
void WriteInfo(string source, string message);
void WriteError(string source, string message);
void WriteStatistics(string source, TimeSpan duration);
public class ConsoleLogger : ILogger
private string functionName {get;init;}
public ConsoleLogger(string functionName = "FunctionName")
=> this.functionName = functionName;
public virtual void WriteInfo(string source, string message)
=> WL($"INFO...\tSource: {source}\n\t\t\t{message}");
public virtual void WriteError(string source, string message)
=> WL($"ERROR...\tSource: {source}\n\t\t\t{message}");
public void WriteStatistics(string source, TimeSpan duration)
=> WL($"STATS...\tSource: {source}\n\t\t\tDuration: {duration.ToString()}");
public class EventViewerLogger : ILogger
private string functionName {get;init;}
public EventViewerLogger(string functionName = "FunctionName")
=> this.functionName = functionName;
public virtual void WriteInfo(string source, string message)
=> EventLog.WriteEntry(source, message);
public virtual void WriteError(string source, string message)
=> EventLog.WriteEntry(source, message);
public void WriteStatistics(string source, TimeSpan duration)
=> EventLog.WriteEntry(source, duration.ToString());
public static class DebugMethods
private static bool debug=true;
public static void DoNothing(){}
public static void L() => Console.Write(debug ? "\n" : "");
public static void W<T>(T str) => Console.Write(debug ? str : "");
public static void WL<T>(T str) => Console.WriteLine(debug ? str : "");