Esempio n. 1
0
        private void BuildAnnotatedMessageHandlers()
        {
            // create a handler for every method which has MessageHandlerAttribute

            var methods = _type.GetMethods(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);

            foreach (var method in methods)
            {
                var attr = method.GetCustomAttribute <MessageHandlerAttribute>();
                if (attr == null)
                {
                    continue;
                }

                var messageType   = attr.Type ?? method.GetParameters()[0].ParameterType;
                var isAsyncMethod = (method.ReturnType.Name.StartsWith("Task"));
                var filterChain   = _filterHandlerBuilder.Build(method, FilterChainKind.Message);
                var isSyncHandler = isAsyncMethod == false && filterChain.AsyncFilterExists == false;
                var isReentrant   = isSyncHandler == false && HandlerBuilderHelpers.IsReentrantMethod(method);

                if (isAsyncMethod == false && method.GetCustomAttribute <AsyncStateMachineAttribute>() != null)
                {
                    throw new InvalidOperationException($"Async void handler is not supported. ({_type.FullName}.{method.Name})");
                }

                AddHandler(method, messageType, filterChain, isSyncHandler, isReentrant);
            }
        }
Esempio n. 2
0
        private static Type[] GetInterfacePayloadTypeTable(Type interfaceType)
        {
            var payloadTypes = (Type[])HandlerBuilderHelpers.GetInterfacePayloadTypeTable(interfaceType, PayloadTableKind.Notification);

            if (payloadTypes == null || payloadTypes.GetLength(0) != interfaceType.GetMethods().Length)
            {
                throw new InvalidOperationException(
                          $"Mismatched a payload table for {interfaceType.FullName}");
            }

            return(payloadTypes);
        }
Esempio n. 3
0
        private void BuildRegularInterfaceHandlers()
        {
            foreach (var ifs in _type.GetInterfaces())
            {
                if (ifs.GetInterfaces().All(t => t != typeof(IInterfacedObserver) && t != typeof(IInterfacedObserverSync)))
                {
                    continue;
                }

                var primaryInterface = ifs;

                var alternativeInterfaceAttribute = ifs.GetCustomAttribute <AlternativeInterfaceAttribute>();
                if (alternativeInterfaceAttribute != null)
                {
                    primaryInterface = alternativeInterfaceAttribute.Type.IsGenericType
                        ? alternativeInterfaceAttribute.Type.MakeGenericType(ifs.GetGenericArguments())
                        : alternativeInterfaceAttribute.Type;
                }

                var interfaceMap = _type.GetInterfaceMap(ifs);
                var methodItems  = interfaceMap.InterfaceMethods.Zip(interfaceMap.TargetMethods, Tuple.Create)
                                   .OrderBy(p => p.Item1, new MethodInfoComparer())
                                   .ToArray();
                var payloadTypeTable = GetInterfacePayloadTypeTable(primaryInterface);

                // build a decorated handler for each method.

                for (var i = 0; i < methodItems.Length; i++)
                {
                    var targetMethod      = methodItems[i].Item2;
                    var invokePayloadType = payloadTypeTable[i];
                    var filterChain       = _filterHandlerBuilder.Build(targetMethod, FilterChainKind.Notification);
                    var isSyncHandler     = alternativeInterfaceAttribute == null && filterChain.AsyncFilterExists == false;
                    var isReentrant       = isSyncHandler == false && HandlerBuilderHelpers.IsReentrantMethod(targetMethod);

                    AddHandler(ifs, targetMethod, invokePayloadType, filterChain, isSyncHandler, isReentrant);
                }
            }
        }
Esempio n. 4
0
        private void BuildExtendedInterfaceHandlers()
        {
            var targetMethods =
                _type.GetMethods(BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.Public)
                .Where(m => m.GetCustomAttribute <ExtendedHandlerAttribute>() != null)
                .Select(m => Tuple.Create(m, m.GetCustomAttribute <ExtendedHandlerAttribute>()))
                .ToList();

            var extendedInterfaces =
                _type.GetInterfaces()
                .Where(t => t.FullName.StartsWith("Akka.Interfaced.IExtendedInterface"))
                .SelectMany(t => t.GenericTypeArguments)
                .Where(t => t.GetInterfaces().Any(i => i == typeof(IInterfacedObserver)));

            // includes base interfaces
            var extendedAllInterfaces = extendedInterfaces
                                        .Concat(extendedInterfaces.SelectMany(t => t.GetInterfaces().Where(u => u != typeof(IInterfacedObserver))))
                                        .Distinct().ToArray();

            foreach (var ifs in extendedAllInterfaces)
            {
                var payloadTypeTable = GetInterfacePayloadTypeTable(ifs);
                var interfaceMethods = ifs.GetMethods().OrderBy(m => m, new MethodInfoComparer()).ToArray();

                // build a decorated handler for each method.

                for (var i = 0; i < interfaceMethods.Length; i++)
                {
                    var interfaceMethod   = interfaceMethods[i];
                    var invokePayloadType = payloadTypeTable[i];
                    var name       = interfaceMethod.Name;
                    var parameters = interfaceMethod.GetParameters();

                    // find a method which can handle this invoke payload

                    MethodInfo targetMethod = null;
                    foreach (var method in targetMethods)
                    {
                        if (method.Item2.Type != null || method.Item2.Method != null)
                        {
                            // check tagged method
                            if (method.Item2.Type != null && method.Item2.Type != ifs)
                            {
                                continue;
                            }
                            if (method.Item2.Method != null && method.Item2.Method != name)
                            {
                                continue;
                            }
                        }
                        else if (method.Item1.Name != name)
                        {
                            // check method
                            continue;
                        }

                        if (HandlerBuilderHelpers.AreParameterTypesEqual(method.Item1.GetParameters(), parameters))
                        {
                            if (targetMethod != null)
                            {
                                throw new InvalidOperationException(
                                          $"Ambiguous handlers for {ifs.FullName}.{interfaceMethod.Name} method.\n" +
                                          $" {targetMethod.Name}\n {method.Item1.Name}\n");
                            }
                            targetMethod = method.Item1;
                        }
                    }
                    if (targetMethod == null)
                    {
                        throw new InvalidOperationException(
                                  $"Cannot find handler for {ifs.FullName}.{interfaceMethod.Name}");
                    }
                    targetMethods.RemoveAll(x => x.Item1 == targetMethod);

                    // build handler

                    var isAsyncMethod = targetMethod.ReturnType.Name.StartsWith("Task");
                    var filterChain   = _filterHandlerBuilder.Build(targetMethod, FilterChainKind.Notification);
                    var isSyncHandler = isAsyncMethod == false && filterChain.AsyncFilterExists == false;
                    var isReentrant   = isSyncHandler == false && HandlerBuilderHelpers.IsReentrantMethod(targetMethod);

                    if (isAsyncMethod == false && targetMethod.GetCustomAttribute <AsyncStateMachineAttribute>() != null)
                    {
                        throw new InvalidOperationException($"Async void handler is not supported. ({_type.FullName}.{targetMethod.Name})");
                    }

                    AddHandler(ifs, targetMethod, invokePayloadType, filterChain, isSyncHandler, isReentrant);
                }
            }
        }