1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495 |
- using Grpc.Core;
- using Grpc.Extension.Abstract;
- using System;
- using System.Collections.Generic;
- using System.Reflection;
- using System.Text;
- namespace Grpc.Extension.AspNetCore.Internal
- {
- internal static class BindMethodFinder
- {
- private const BindingFlags BindMethodBindingFlags = BindingFlags.Public | BindingFlags.Static;
-
- internal static MethodInfo GetBindMethod(Type serviceType)
- {
- if (typeof(IGrpcService).IsAssignableFrom(serviceType))
- {
- return typeof(GrpcMethodHelper).GetMethod("BindService");
- }
- else
- {
- // Prefer finding the bind method using attribute on the generated service
- var bindMethodInfo = GetBindMethodUsingAttribute(serviceType);
- if (bindMethodInfo == null)
- {
- // Fallback to searching for bind method using known type hierarchy that Grpc.Tools generates
- bindMethodInfo = GetBindMethodFallback(serviceType);
- }
- return bindMethodInfo;
- }
- }
- internal static MethodInfo GetBindMethodUsingAttribute(Type serviceType)
- {
- Type currentServiceType = serviceType;
- BindServiceMethodAttribute bindServiceMethod;
- do
- {
- // Search through base types for bind service attribute
- // We need to know the base service type because it is used with GetMethod below
- bindServiceMethod = currentServiceType.GetCustomAttribute<BindServiceMethodAttribute>();
- if (bindServiceMethod != null)
- {
- // Bind method will be public and static
- // Two parameters: ServiceBinderBase and the service type
- return bindServiceMethod.BindType.GetMethod(
- bindServiceMethod.BindMethodName,
- BindMethodBindingFlags,
- binder: null,
- new[] { typeof(ServiceBinderBase), currentServiceType },
- Array.Empty<ParameterModifier>());
- }
- } while ((currentServiceType = currentServiceType.BaseType) != null);
- return null;
- }
- internal static MethodInfo GetBindMethodFallback(Type serviceType)
- {
- // Search for the generated service base class
- var baseType = GetServiceBaseType(serviceType);
- if (baseType == null)
- {
- return null;
- }
- // We need to call Foo.BindService from the declaring type.
- var declaringType = baseType.DeclaringType;
- // The method we want to call is public static void BindService(ServiceBinderBase, BaseType)
- return declaringType?.GetMethod(
- "BindService",
- BindMethodBindingFlags,
- binder: null,
- new[] { typeof(ServiceBinderBase), baseType },
- Array.Empty<ParameterModifier>());
- }
- private static Type GetServiceBaseType(Type serviceImplementation)
- {
- // TService is an implementation of the gRPC service. It ultimately derives from Foo.TServiceBase base class.
- // We need to access the static BindService method on Foo which implicitly derives from Object.
- var baseType = serviceImplementation.BaseType;
- // Handle services that have multiple levels of inheritence
- while (baseType?.BaseType?.BaseType != null)
- {
- baseType = baseType.BaseType;
- }
- return baseType;
- }
- }
- }
|