public static string GetMethodName(Type type) { if (MethodNames.TryGetValue(type, out var method)) { return(method); } // Custom method var attribute = MethodAttribute.From(type); var handler = KnownHandlers.SelectMany(z => z) .FirstOrDefault(z => z.InterfaceType == type || z.HandlerType == type || z.ParamsType == type); if (handler != null) { return(handler.Method); } // TODO: Log unknown method name if (attribute is null) { return(null); } MethodNames.TryAdd(type, attribute.Method); return(attribute.Method); }
static HandlerTypeDescriptorHelper() { try { KnownHandlers = AppDomain.CurrentDomain.GetAssemblies() .SelectMany( x => { try { return(x.GetTypes()); } catch { return(Enumerable.Empty <Type>()); } } ) .Where(z => (z.IsInterface || (z.IsClass && !z.IsAbstract)) && typeof(IJsonRpcHandler).IsAssignableFrom(z)) .Where(z => MethodAttribute.From(z) != null) .Where(z => !z.Name.EndsWith("Manager")) // Manager interfaces are generally specializations around the handlers .Select(GetMethodType) .Distinct() .ToLookup(x => MethodAttribute.From(x).Method) .SelectMany(x => x.Select(z => new HandlerTypeDescriptor(z) as IHandlerTypeDescriptor)) .ToLookup(x => x.Method, StringComparer.Ordinal); } catch (Exception e) { throw new AggregateException("Failed", e); } }
internal static IEnumerable <IHandlerTypeDescriptor> GetDescriptors(IEnumerable <Assembly> assemblies) => assemblies.SelectMany( x => { try { return(x.GetTypes()); } catch { return(Enumerable.Empty <Type>()); } } ) .Where(z => z.IsInterface || z.IsClass && !z.IsAbstract) // running on mono this call can cause issues when scanning of the entire assembly. .Where( z => { try { return(typeof(IJsonRpcHandler).IsAssignableFrom(z)); } catch { return(false); } } ) .Where(z => MethodAttribute.From(z) != null) .Where(z => !z.Name.EndsWith("Manager")) // Manager interfaces are generally specializations around the handlers .Select(HandlerTypeDescriptorHelper.GetMethodType) .Distinct() .ToLookup(x => MethodAttribute.From(x) !.Method)
public HandlerTypeDescriptor(Type handlerType) { var method = MethodAttribute.From(handlerType) !; Method = method.Method; Direction = method.Direction; if (handlerType.IsGenericTypeDefinition && handlerType.IsPublic) { var parameter = handlerType.GetTypeInfo().GenericTypeParameters[0]; var constraints = parameter.GetGenericParameterConstraints(); if (constraints.Length == 1) { handlerType = handlerType.MakeGenericType(handlerType.GetTypeInfo().GenericTypeParameters[0].GetGenericParameterConstraints()[0]); } } HandlerType = handlerType; InterfaceType = HandlerTypeDescriptorHelper.GetHandlerInterface(handlerType); // This allows for us to have derived types // We are making the assumption that interface given here // if a GTD will have a constraint on the first generic type parameter // that is the real base type for this interface. if (InterfaceType.IsGenericType) { ParamsType = InterfaceType.GetGenericArguments()[0]; } HasParamsType = ParamsType != null; IsNotification = handlerType .GetInterfaces() .Any(z => z.IsGenericType && typeof(IJsonRpcNotificationHandler <>).IsAssignableFrom(z.GetGenericTypeDefinition())); IsRequest = !IsNotification; var requestInterface = ParamsType? .GetInterfaces() .FirstOrDefault(x => x.IsGenericType && x.GetGenericTypeDefinition() == typeof(IRequest <>)); if (requestInterface != null) { ResponseType = requestInterface.GetGenericArguments()[0]; } HasResponseType = ResponseType != null && ResponseType != typeof(Unit); var processAttributes = HandlerType .GetCustomAttributes(true) .Concat(HandlerType.GetCustomAttributes(true)) .Concat(InterfaceType.GetInterfaces().SelectMany(x => x.GetCustomAttributes(true))) .Concat(HandlerType.GetInterfaces().SelectMany(x => x.GetCustomAttributes(true))) .OfType <ProcessAttribute>() .ToArray(); RequestProcessType = processAttributes .FirstOrDefault()?.Type; }
internal static Type GetMethodType(Type type) { // Custom method if (MethodAttribute.AllFrom(type).Any()) { return(type); } return(type.GetTypeInfo() .ImplementedInterfaces .FirstOrDefault(t => MethodAttribute.AllFrom(t).Any())); }