public static void Invoke(Object obj, DomainEvent domainEvent) { if (!invokerCache.ContainsKey(obj.GetType())) { var typeCache = new Dictionary<Type, MethodInvoker>(); var applyMethods = obj.GetType().GetMethods( BindingFlags.NonPublic | BindingFlags.Instance); foreach (var item in applyMethods .Where(am => am.Name.Equals("apply", StringComparison.OrdinalIgnoreCase)) .Select(am => new { parameters = am.GetParameters(), minfo = am }) .Where(p => p.parameters.Length == 1 && typeof(DomainEvent).IsAssignableFrom(p.parameters[0].ParameterType))) { var localItem = item; typeCache[localItem.parameters[0].ParameterType] = item.minfo.DelegateForCallMethod(); } invokerCache[obj.GetType()] = typeCache; } var thisTypeCache = invokerCache[obj.GetType()]; MethodInvoker invoker; if (thisTypeCache.TryGetValue(domainEvent.GetType(), out invoker)) { invoker.Invoke(obj, domainEvent); } }