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")) },