/// <summary> /// InitHandler /// </summary> private void InitHandler() { Assembly assembly = typeof(MySqlService).Assembly; Type[] types = assembly.GetTypes(); foreach (var type in types) { var attributes = type.GetCustomAttributes(typeof(HandlerAttribute), false); foreach (var attr in attributes) { HandlerAttribute handlerAttribute = (HandlerAttribute)attr; object obj = Activator.CreateInstance(type); BaseHandler baseHandler = obj as BaseHandler; if (baseHandler == null) { log.Warn($"没有继承BaseHandler:{type.Name}"); continue; } if (!handlerDic.ContainsKey(handlerAttribute.Tag)) { handlerDic.Add(handlerAttribute.Tag, baseHandler); } else { log.Warn($"key值重复:{handlerAttribute.Tag}"); } } } log.Info($"handlerCount:{handlerDic.Count}"); }
public SnapshotHandler() { var thisType = GetType(); var handlerAttributes = thisType.GetCustomAttributes(typeof(HandlerAttribute), false); if (handlerAttributes.Length > 0) { handlerAttribute = (HandlerAttribute)handlerAttributes[0]; } else { handlerAttribute = default; } foreach (var method in GetType().GetMethods()) { var parameters = method.GetParameters(); if (parameters.Length >= 2 && method.Name != nameof(Apply) && typeof(IEvent).IsAssignableFrom(parameters[1].ParameterType)) { if (!method.IsStatic) { throw new NotSupportedException("method must be static"); } var evtType = parameters[1].ParameterType; if (parameters.Length == 2) { var dynamicMethod = new DynamicMethod($"{evtType.Name}_handler", typeof(void), new Type[] { parameters[0].ParameterType, typeof(IEvent) }, thisType, true); var ilGen = dynamicMethod.GetILGenerator(); ilGen.DeclareLocal(evtType); ilGen.Emit(OpCodes.Ldarg_1); ilGen.Emit(OpCodes.Castclass, evtType); ilGen.Emit(OpCodes.Stloc_0); ilGen.Emit(OpCodes.Ldarg_0); ilGen.Emit(OpCodes.Ldloc_0); ilGen.Emit(OpCodes.Call, method); ilGen.Emit(OpCodes.Ret); var func = (Action <Snapshot, IEvent>)dynamicMethod.CreateDelegate(typeof(Action <Snapshot, IEvent>)); _handlerDict.Add(evtType, func); } else if (parameters[2].ParameterType == typeof(EventBase)) { var dynamicMethod = new DynamicMethod($"{evtType.Name}_handler", typeof(void), new Type[] { parameters[0].ParameterType, typeof(IEvent), typeof(EventBase) }, thisType, true); var ilGen = dynamicMethod.GetILGenerator(); ilGen.DeclareLocal(evtType); ilGen.Emit(OpCodes.Ldarg_1); ilGen.Emit(OpCodes.Castclass, evtType); ilGen.Emit(OpCodes.Stloc_0); ilGen.Emit(OpCodes.Ldarg_0); ilGen.Emit(OpCodes.Ldloc_0); ilGen.Emit(OpCodes.Ldarg_2); ilGen.Emit(OpCodes.Call, method); ilGen.Emit(OpCodes.Ret); var func = (Action <Snapshot, IEvent, EventBase>)dynamicMethod.CreateDelegate(typeof(Action <Snapshot, IEvent, EventBase>)); _handlerDict_1.Add(evtType, func); } } } }
public HandlerAttributeData GetData(MemberInfo info) { if (info is Type) { return(new HandlerAttributeData(MainName, null)); } HandlerAttribute attribute = (HandlerAttribute)info.DeclaringType.GetCustomAttributes(typeof(HandlerAttribute), true)[0]; return(new HandlerAttributeData(attribute.MainName, SubName)); }
public ObserverGrain() { GrainType = GetType(); var handlerAttributes = GrainType.GetCustomAttributes(typeof(HandlerAttribute), false); if (handlerAttributes.Length > 0) { handlerAttribute = (HandlerAttribute)handlerAttributes[0]; } else { handlerAttribute = default; } foreach (var method in GrainType.GetMethods()) { var parameters = method.GetParameters(); if (parameters.Length >= 1 && typeof(IEvent).IsAssignableFrom(parameters[0].ParameterType)) { var evtType = parameters[0].ParameterType; if (parameters.Length == 2 && parameters[1].ParameterType == typeof(EventBase)) { var dynamicMethod = new DynamicMethod($"{evtType.Name}_handler", typeof(Task), new Type[] { typeof(object), typeof(IEvent), typeof(EventBase) }, GrainType, true); var ilGen = dynamicMethod.GetILGenerator();//IL生成器 ilGen.DeclareLocal(evtType); ilGen.Emit(OpCodes.Ldarg_1); ilGen.Emit(OpCodes.Castclass, evtType); ilGen.Emit(OpCodes.Stloc_0); ilGen.Emit(OpCodes.Ldarg_0); ilGen.Emit(OpCodes.Ldloc_0); ilGen.Emit(OpCodes.Ldarg_2); ilGen.Emit(OpCodes.Call, method); ilGen.Emit(OpCodes.Ret); var func = (Func <object, IEvent, EventBase, Task>)dynamicMethod.CreateDelegate(typeof(Func <object, IEvent, EventBase, Task>)); _handlerDict_1.Add(evtType, func); } else { var dynamicMethod = new DynamicMethod($"{evtType.Name}_handler", typeof(Task), new Type[] { typeof(object), typeof(IEvent) }, GrainType, true); var ilGen = dynamicMethod.GetILGenerator();//IL生成器 ilGen.DeclareLocal(evtType); ilGen.Emit(OpCodes.Ldarg_1); ilGen.Emit(OpCodes.Castclass, evtType); ilGen.Emit(OpCodes.Stloc_0); ilGen.Emit(OpCodes.Ldarg_0); ilGen.Emit(OpCodes.Ldloc_0); ilGen.Emit(OpCodes.Call, method); ilGen.Emit(OpCodes.Ret); var func = (Func <object, IEvent, Task>)dynamicMethod.CreateDelegate(typeof(Func <object, IEvent, Task>)); _handlerDict_0.Add(evtType, func); } } } }
public void AcceptOnErrorAlwaysRejectsWhenErrorsAreNotPresent() { Mock <IQueueWrapper> qw = new Mock <IQueueWrapper>(); Mock <ILogger> log = new Mock <ILogger>(); Mock <IConfigurationManager> config = new Mock <IConfigurationManager>(); Mock <IMethodInspectorManager> mim = new Mock <IMethodInspectorManager>(); MessageSubscriber subscriber = new MessageSubscriber(qw.Object, log.Object, config.Object, metrics, mim.Object, Mock.Of <IContainerFacade>()); HandlerAttribute handlerAttribute = new HandlerAttribute("Blah") { ErrorsBehaviour = ErrorsBehaviour.AcceptOnlyIfErrorsExist, AcceptanceBehaviour = AcceptanceBehaviour.OnlyWithoutSolution }; object message = new Message <string, bool>() { }; Assert.IsFalse(subscriber.ProcessAcceptanceBehaviours(handlerAttribute, typeof(Message <string, bool>), message)); }
public SnapshotHandler() { var thisType = GetType(); var handlerAttributes = thisType.GetCustomAttributes(typeof(HandlerAttribute), false); if (handlerAttributes.Length > 0) { handlerAttribute = (HandlerAttribute)handlerAttributes[0]; } else { handlerAttribute = default; } var methods = GetType().GetMethods().Where(m => { var parameters = m.GetParameters(); return(parameters.Length >= 2 && parameters.Any(p => p.ParameterType == typeof(Snapshot)) && parameters.Any(p => typeof(IEvent).IsAssignableFrom(p.ParameterType))); }).ToList(); var dynamicMethod = new DynamicMethod($"Handler_Invoke", typeof(void), new Type[] { typeof(object), typeof(Snapshot), typeof(IEvent), typeof(EventBase) }, thisType, true); var ilGen = dynamicMethod.GetILGenerator(); var items = new List <SwitchMethodEmit>(); for (int i = 0; i < methods.Count; i++) { var method = methods[i]; var methodParams = method.GetParameters(); var caseType = methodParams.Single(p => typeof(IEvent).IsAssignableFrom(p.ParameterType)).ParameterType; items.Add(new SwitchMethodEmit { Mehod = method, CaseType = caseType, DeclareLocal = ilGen.DeclareLocal(caseType), Lable = ilGen.DefineLabel(), Parameters = methodParams, Index = i }); } var defaultLabel = ilGen.DefineLabel(); foreach (var item in items) { ilGen.Emit(OpCodes.Ldarg_2); ilGen.Emit(OpCodes.Isinst, item.CaseType); if (item.Index > 3) { ilGen.Emit(OpCodes.Stloc_S, item.DeclareLocal); ilGen.Emit(OpCodes.Ldloc_S, item.DeclareLocal); } else { if (item.Index == 0) { ilGen.Emit(OpCodes.Stloc_0); ilGen.Emit(OpCodes.Ldloc_0); } else if (item.Index == 1) { ilGen.Emit(OpCodes.Stloc_1); ilGen.Emit(OpCodes.Ldloc_1); } else if (item.Index == 2) { ilGen.Emit(OpCodes.Stloc_2); ilGen.Emit(OpCodes.Ldloc_2); } else { ilGen.Emit(OpCodes.Stloc_3); ilGen.Emit(OpCodes.Ldloc_3); } } ilGen.Emit(OpCodes.Brtrue_S, item.Lable); } ilGen.Emit(OpCodes.Br_S, defaultLabel); foreach (var item in items) { ilGen.MarkLabel(item.Lable); ilGen.Emit(OpCodes.Ldarg_0); //加载第一个参数 if (item.Parameters[0].ParameterType == typeof(Snapshot)) { ilGen.Emit(OpCodes.Ldarg_1); } else if (item.Parameters[0].ParameterType == typeof(EventBase)) { ilGen.Emit(OpCodes.Ldarg_3); } else { LdEventArgs(item, ilGen); } //加载第二个参数 if (item.Parameters[1].ParameterType == typeof(Snapshot)) { ilGen.Emit(OpCodes.Ldarg_1); } else if (item.Parameters[1].ParameterType == typeof(EventBase)) { ilGen.Emit(OpCodes.Ldarg_3); } else { LdEventArgs(item, ilGen); } //加载第三个参数 if (item.Parameters.Length == 3) { if (item.Parameters[1].ParameterType == typeof(Snapshot)) { ilGen.Emit(OpCodes.Ldarg_1); } else if (item.Parameters[1].ParameterType == typeof(EventBase)) { ilGen.Emit(OpCodes.Ldarg_3); } else { LdEventArgs(item, ilGen); } } ilGen.Emit(OpCodes.Call, item.Mehod); ilGen.Emit(OpCodes.Ret); } ilGen.MarkLabel(defaultLabel); ilGen.Emit(OpCodes.Ldarg_0); ilGen.Emit(OpCodes.Ldarg_2); ilGen.Emit(OpCodes.Call, thisType.GetMethod(nameof(DefaultHandler))); ilGen.Emit(OpCodes.Ret); handlerInvokeFunc = (Action <object, Snapshot, IEvent, EventBase>)dynamicMethod.CreateDelegate(typeof(Action <object, Snapshot, IEvent, EventBase>));
AuthorizationCallHandler GetHandlerFromAttribute(HandlerAttribute attribute) { return((AuthorizationCallHandler)attribute.CreateHandler(container)); }
PerformanceCounterCallHandler GetHandlerFromAttribute(HandlerAttribute attribute) { return((PerformanceCounterCallHandler)attribute.CreateHandler(null)); }
public Task ConsumeMessage(object sender, BasicDeliverEventArgs eventDetails) { try { inProgressMessages++; if (eventDetails?.Body == null || eventDetails.Body.Length < 1) { return(RejectMessageWith(DiscardedMessageReason.MissingMessageBody, eventDetails)); } // Deserialise into a class containing only Method and UUID - this also generates a hash MethodInspector inspector = GetMethodInspector(eventDetails); if (inspector == null) { return(RejectMessageWith(DiscardedMessageReason.MethodDeserialisationError, eventDetails)); } _logger.Trace($"{nameof(MessageSubscriber)}.{nameof(ConsumeMessage)}", new LogItem("Event", "Message routed"), new LogItem("Calculated hashcode", inspector.Hash), new LogItem("MessageId", inspector.Uuid.ToString), new LogItem("MessageMethod", inspector.Method)); if (MessageIsDuplicate(inspector)) { return(RejectMessageWith(DiscardedMessageReason.Duplicate, eventDetails)); } Type handlerType = GetMessageHandlers(inspector); if (handlerType == null) { _logger.Trace($"{nameof(MessageSubscriber)}.{nameof(ConsumeMessage)}", new LogItem("Event", "No suitable handler found for Method " + inspector.Method)); // We can't process this message, so we'll Ack it. _methodInspectorManager.Register(inspector); // we don't want to see it again return(RejectMessageWith(DiscardedMessageReason.NoHandler, eventDetails)); } Type[] genericArguments = GetGenericArguments(handlerType, inspector.Uuid); if (handlerType.GetTypeInfo().ContainsGenericParameters) { handlerType = handlerType.MakeGenericType(genericArguments); } string bodyAsString = Encoding.UTF8.GetString(eventDetails.Body); if (!ConstructMessage(out object message, genericArguments, bodyAsString, inspector.Uuid)) { _logger.Trace($"{nameof(MessageSubscriber)}.{nameof(ConsumeMessage)}", new LogItem("Event", "The Message could not be constructed, so it's been discarded.")); _methodInspectorManager.Register(inspector); // we don't want to see it again // This is a Permanent Failure; if we couldn't construct the Message object now, processing it again won't help. return(RejectMessageWith(DiscardedMessageReason.MessageDeserialisationError, eventDetails)); } Type messageType = message.GetType(); PropertyInfo need; lock (NeedPropertyCache) { if (!NeedPropertyCache.ContainsKey(messageType)) { NeedPropertyCache.Add(messageType, messageType.GetProperty(nameof(Message <object, object> .Need))); } need = NeedPropertyCache[messageType]; } if (need.GetValue(message) == null) { _logger.Warn($"{nameof(MessageSubscriber)}.{nameof(ConsumeMessage)}", new LogItem("Event", "Message has no Need"), new LogItem("MessageId", inspector.Uuid.ToString)); _methodInspectorManager.Register(inspector); // we don't want to see it again // This is a Permanent Failure; if there's no Need in the message now, processing it again won't change anything. return(RejectMessageWith(DiscardedMessageReason.MissingNeed, eventDetails)); } HandlerAttribute handlerAttribute = handlerType.GetTypeInfo().GetCustomAttributes <HandlerAttribute>().FirstOrDefault(a => a.Method == inspector.Method); if (!ProcessAcceptanceBehaviours(handlerAttribute, messageType, message)) { _methodInspectorManager.Register(inspector); // we don't want to see it again return(RejectMessageWith(DiscardedMessageReason.AcceptanceBehaviourPrecondition, eventDetails)); } _logger.Trace($"{nameof(MessageSubscriber)}.{nameof(ConsumeMessage)}", new LogItem("Event", "Constructing handler"), new LogItem("MessageId", inspector.Uuid.ToString), new LogItem("HandlerName", handlerType.Name)); var stopWatch = Stopwatch.StartNew(); CompletionAction invocationResult = InvokeHandleMethod(inspector.Uuid, handlerType, message); stopWatch.Stop(); _metrics.RecordProcessedMessage(handlerType.Name, stopWatch.Elapsed.TotalMilliseconds); if (invocationResult == CompletionAction.Republish) { publishMethod = publishMethod ?? _queueWrapper.GetType().GetMethod(nameof(_queueWrapper.PublishMessage)); publishMethod.MakeGenericMethod(genericArguments).Invoke(_queueWrapper, new object[] { message, inspector.Uuid }); } // Any exceptions thrown up to this point *are probably* Temporary Failures: // Permanent Failures will have been dealt with by local Exception Handling, // and the code will continue to this point. _methodInspectorManager.Register(inspector); _queueWrapper.AcknowledgeMessage(eventDetails); } catch (Exception e) { _logger.Exception($"{nameof(MessageSubscriber)}.{nameof(ConsumeMessage)}", "Failure during consuming of message", e); throw; } finally { inProgressMessages--; } return(Task.CompletedTask); }
public bool ProcessAcceptanceBehaviours(HandlerAttribute handlerAttribute, Type messageType, object message) { if (handlerAttribute == null || handlerAttribute.AcceptanceBehaviour == AcceptanceBehaviour.Always) { return(true); } bool rejectOnError = handlerAttribute.ErrorsBehaviour == ErrorsBehaviour.RejectIfErrorsExist; bool acceptOnlyOnError = handlerAttribute.ErrorsBehaviour == ErrorsBehaviour.AcceptOnlyIfErrorsExist; if (rejectOnError || acceptOnlyOnError) { PropertyInfo errors; lock (ErrorsPropertyCache) { if (!ErrorsPropertyCache.ContainsKey(messageType)) { ErrorsPropertyCache.Add(messageType, messageType.GetProperty(nameof(Message <object, object> .Errors))); } errors = ErrorsPropertyCache[messageType]; } object errorsValue = errors.GetValue(message); if (rejectOnError && errorsValue != null) { // if it's not null and not IList then we have to assume that there are errors in whatever it is we've got. if (!(errorsValue is IList list) || list.Count > 0) { return(false); } } if (acceptOnlyOnError) { if (errorsValue == null || errorsValue is IList list && list.Count == 0) { return(false); } } } PropertyInfo solution; lock (SolutionPropertyCache) { if (!SolutionPropertyCache.ContainsKey(messageType)) { SolutionPropertyCache.Add(messageType, messageType.GetProperty(nameof(Message <object, object> .Solution))); } solution = SolutionPropertyCache[messageType]; } object solutionValue = solution.GetValue(message); if (handlerAttribute.AcceptanceBehaviour == AcceptanceBehaviour.OnlyWithSolution && solutionValue == null) { return(false); } if (handlerAttribute.AcceptanceBehaviour == AcceptanceBehaviour.OnlyWithoutSolution && solutionValue != null) { return(false); } return(true); }