/// <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}");
        }
예제 #2
0
        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));
    }
예제 #4
0
        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));
        }
예제 #6
0
        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));
 }
예제 #9
0
        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);
        }
예제 #10
0
        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);
        }