Example #1
0
        public HandlerDescriptor(
            string method, IHandlerTypeDescriptor typeDescriptor, IJsonRpcHandler handler, Type handlerInterface, Type @params, Type response,
            RequestProcessType?requestProcessType, Action disposeAction
            )
        {
            _disposeAction     = disposeAction;
            Handler            = handler;
            ImplementationType = handler.GetType();
            Method             = method;
            TypeDescriptor     = typeDescriptor;
            HandlerType        = handlerInterface;
            Params             = @params;
            Response           = response;
            HasReturnType      = HandlerType.GetInterfaces().Any(
                @interface =>
                @interface.IsGenericType &&
                typeof(IRequestHandler <,>).IsAssignableFrom(@interface.GetGenericTypeDefinition())
                );

            IsDelegatingHandler = @params?.IsGenericType == true &&
                                  (
                typeof(DelegatingRequest <>).IsAssignableFrom(@params.GetGenericTypeDefinition()) ||
                typeof(DelegatingNotification <>).IsAssignableFrom(@params.GetGenericTypeDefinition())
                                  );

            IsNotification = handlerInterface.GetInterfaces().Any(
                z => z.IsGenericType &&
                typeof(IJsonRpcNotificationHandler <>).IsAssignableFrom(z.GetGenericTypeDefinition())
                );
            IsRequest          = !IsNotification;
            RequestProcessType = requestProcessType;
        }
        public void HandlersShouldExtensionMethodClassWithMethods(IHandlerTypeDescriptor descriptor, string onMethodName, string sendMethodName,
                                                                  Type extensionClass, string extensionClassName)
        {
            // This test requires a refactor, the delegating handlers have been removed and replaced by shared implementations
            // TODO:
            // * Check for IPartialItem(s)<> extension methods
            // * Also update events to have a nicer fire and forget abstract class

            _logger.LogInformation("Handler: {Type} {Extension} {ExtensionName} {OnMethod} {SendMethod}", descriptor.HandlerType,
                                   extensionClass, extensionClassName, onMethodName, sendMethodName);

            extensionClass.Should().NotBeNull($"{descriptor.HandlerType.FullName} is missing extension method class");
            extensionClass.GetMethods().Any(z => z.Name == onMethodName && typeof(IJsonRpcHandlerRegistry).IsAssignableFrom(z.GetParameters()[0].ParameterType)).Should()
            .BeTrue($"{descriptor.HandlerType.FullName} is missing event extension methods named {onMethodName}");
            extensionClass.GetMethods().Any(z => z.Name == sendMethodName && typeof(IResponseRouter).IsAssignableFrom(z.GetParameters()[0].ParameterType)).Should()
            .BeTrue($"{descriptor.HandlerType.FullName} is missing execute extension methods named {sendMethodName}");

            var registries = extensionClass.GetMethods(BindingFlags.Static | BindingFlags.Public)
                             .Where(z => z.Name == onMethodName || z.Name == sendMethodName)
                             .Select(z => z.GetParameters()[0].ParameterType)
                             .Distinct()
                             .ToHashSet();

            registries.Should().HaveCount(descriptor.Direction == Direction.Bidirectional ? 4 : 2,
                                          $"{descriptor.HandlerType.FullName} there should be methods for both handing the event and sending the event");
        }
        public void HandlersShouldAbstractClass(IHandlerTypeDescriptor descriptor)
        {
            _logger.LogInformation("Handler: {Type}", descriptor.HandlerType);
            // This test requires a refactor, the delegating handlers have been removed and replaced by shared implementations
            // TODO:
            // * Check for extension methods
            // * Check for IPartialItem(s)<> extension methods
            // * Check that the extension method calls `AddHandler` using the correct eventname
            // * check extension method name
            // * Also update events to have a nicer fire and forget abstract class
            // * Ensure all notifications have an action and task returning function
            var abstractHandler = descriptor.HandlerType.Assembly.ExportedTypes.FirstOrDefault(z => z.IsAbstract && z.IsClass && descriptor.HandlerType.IsAssignableFrom(z));

            abstractHandler.Should().NotBeNull($"{descriptor.HandlerType.FullName} is missing abstract base class");

            var delegatingHandler = descriptor.HandlerType.Assembly.DefinedTypes.FirstOrDefault(z => abstractHandler.IsAssignableFrom(z) && abstractHandler != z);

            if (delegatingHandler != null)
            {
                _logger.LogInformation("Delegating Handler: {Type}", delegatingHandler);
                delegatingHandler.DeclaringType.Should().NotBeNull();
                delegatingHandler.DeclaringType.GetMethods(BindingFlags.Public | BindingFlags.Static).Any(z => z.Name.StartsWith("On")).Should()
                .BeTrue($"{descriptor.HandlerType.FullName} is missing delegating extension method");
            }
        }
 public MethodMatcher(IEnumerable <Type> registries,
                      IHandlerTypeDescriptor descriptor, Type extensionClass, string methodName)
 {
     _registries     = registries;
     _descriptor     = descriptor;
     _extensionClass = extensionClass;
     _methodName     = methodName;
 }
        public void HandlersShouldHaveExpectedExtensionMethodsBasedOnDirection(IHandlerTypeDescriptor descriptor, string onMethodName, string sendMethodName,
                                                                               Type extensionClass, string extensionClassName)
        {
            _logger.LogInformation("Handler: {Type} {Extension} {ExtensionName} {OnMethod} {SendMethod}", descriptor.HandlerType,
                                   extensionClass, extensionClassName, onMethodName, sendMethodName);

            var onMethodRegistries = extensionClass.GetMethods(BindingFlags.Static | BindingFlags.Public)
                                     .Where(z => z.Name == onMethodName)
                                     .Select(z => z.GetParameters()[0].ParameterType)
                                     .Distinct()
                                     .ToHashSet();

            var sendMethodRegistries = extensionClass.GetMethods(BindingFlags.Static | BindingFlags.Public)
                                       .Where(z => z.Name == sendMethodName)
                                       .Select(z => z.GetParameters()[0].ParameterType)
                                       .Distinct()
                                       .ToHashSet();

            var expectedEventRegistries = descriptor.Direction switch {
                Direction.ClientToServer => new (string type, Func <ParameterInfo, bool> matcher)[] { ("Server", info => info.ParameterType.Name.EndsWith("ServerRegistry")) },