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(IInterfacedActor)))
.ToArray();
// includes base interfaces
var extendedAllInterfaces = extendedInterfaces
.Concat(extendedInterfaces.SelectMany(t => t.GetInterfaces().Where(u => u != typeof(IInterfacedActor))))
.Distinct().ToArray();
foreach (var ifs in extendedAllInterfaces)
{
var payloadTypeTable = GetInterfacePayloadTypeTable(ifs);
var interfaceMethods = ifs.GetMethods().OrderBy(m => m, new MethodInfoComparer()).ToArray();
for (var i = 0; i < interfaceMethods.Length; i++)
{
var interfaceMethod = interfaceMethods[i];
var invokePayloadType = payloadTypeTable[i, 0];
var returnPayloadType = payloadTypeTable[i, 1];
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.Request);
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, returnPayloadType, filterChain, isSyncHandler, isReentrant);
}
}
}