Created
October 8, 2015 08:54
-
-
Save abdullin/72f2dd53a3269112b255 to your computer and use it in GitHub Desktop.
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
public sealed class RedirectToDynamicEvent | |
{ | |
public readonly IDictionary<Type, List<Wire>> Dict = new Dictionary<Type, List<Wire>>(); | |
public sealed class Wire | |
{ | |
readonly MethodInfo _method; | |
public Type ParameterType; | |
readonly object _subject; | |
readonly bool _includeVersion; | |
public readonly string SubjectName ; | |
public Wire(MethodInfo method, Type parameterType, object subject, bool includeVersion) | |
{ | |
if (subject == null) throw new ArgumentNullException("subject"); | |
SubjectName = subject.GetType().Name; | |
_method = method; | |
ParameterType = parameterType; | |
_subject = subject; | |
_includeVersion = includeVersion; | |
} | |
public void Call( object evt, long version) | |
{ | |
if (_includeVersion) | |
{ | |
_method.Invoke(_subject, new[] { evt, version }); | |
} | |
else | |
{ | |
_method.Invoke(_subject, new[] { evt }); | |
} | |
} | |
} | |
static readonly MethodInfo InternalPreserveStackTraceMethod = | |
typeof(Exception).GetMethod("InternalPreserveStackTrace", BindingFlags.Instance | BindingFlags.NonPublic); | |
static Wire ExtractHandlerInfo(object subject, MethodInfo info) | |
{ | |
var parameters = info.GetParameters(); | |
if (parameters.Length == 0 || parameters.Length > 2) | |
{ | |
throw new ArgumentException("We allow only 1 or 2 parameters on " + this.GetType().Name); | |
} | |
bool includeVersion = false; | |
var type = parameters[0].ParameterType; | |
if (parameters.Length == 2) | |
{ | |
if (parameters[1].ParameterType != typeof(long)) | |
{ | |
throw new ArgumentException("Second parameter can only be a long on " + this.GetType().Name); | |
} | |
includeVersion = true; | |
} | |
return new Wire(info, type, subject, includeVersion); | |
} | |
public void WireToWhen(object o) | |
{ | |
var infos = o.GetType() | |
.GetMethods(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance) | |
.Where(m => m.Name == "When") | |
.Where(m => | |
{ | |
var length = m.GetParameters().Length; | |
return length >=1 && length <= 2; | |
}); | |
foreach (var methodInfo in infos) | |
{ | |
if (null == methodInfo) | |
throw new InvalidOperationException(); | |
var handler = ExtractHandlerInfo(o, methodInfo); | |
List<Wire> list; | |
if (!Dict.TryGetValue(handler.ParameterType, out list)) | |
{ | |
list = new List<Wire>(); | |
Dict.Add(handler.ParameterType, list); | |
} | |
list.Add(handler); | |
} | |
} | |
[DebuggerNonUserCode] | |
public void InvokeEvent(object evt, long version) | |
{ | |
var type = evt.GetType(); | |
List<Wire> info; | |
if (!Dict.TryGetValue(type, out info)) | |
return; | |
try | |
{ | |
var sw = new Stopwatch(); | |
foreach (var wire in info) | |
{ | |
sw.Restart(); | |
try | |
{ | |
wire.Call(evt, version); | |
} | |
catch (ArgumentNullException ex) | |
{ | |
this.Log().Error(ex, "Error processing event {0}", evt); | |
} | |
catch (NullReferenceException ex) | |
{ | |
this.Log().Error(ex, "Error processing event {0}", evt); | |
} | |
sw.Stop(); | |
var seconds = sw.Elapsed.TotalSeconds; | |
var handler = wire.SubjectName; | |
var message = type.Name; | |
if (seconds > 1) | |
{ | |
// record time spent by the handling method, only if we are relatively slow | |
Metrics.Timer("domain.events." + message + "." + handler + ".handle-ms", (int)sw.ElapsedMilliseconds); | |
} | |
if (seconds > 2) | |
{ | |
this.Log() | |
.Warn("[Warn]: {handler}\ttook {seconds} seconds to process event {event}", handler, seconds, evt.ToString()); | |
} | |
} | |
} | |
catch (TargetInvocationException ex) | |
{ | |
if (null != InternalPreserveStackTraceMethod) | |
InternalPreserveStackTraceMethod.Invoke(ex.InnerException, new object[0]); | |
throw ex.InnerException; | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment