using IpcLibrary.Core;
using IpcLibrary.Core.Exceptions;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Text;
using System.Threading.Tasks;
namespace IpcLibrary.Services {
///
/// 方法调用处理器
///
public class MethodCallHandler {
private readonly IServiceRegistry _serviceRegistry;
public MethodCallHandler(IServiceRegistry serviceRegistry) {
_serviceRegistry = serviceRegistry ?? throw new ArgumentNullException(nameof(serviceRegistry));
}
public async Task HandleMethodCallAsync(MethodCallRequest request) {
try {
var service = _serviceRegistry.GetService(request.ServiceName);
if (service == null) {
return new MethodCallResponse {
Exception = new IPCException($"服务 '{request.ServiceName}' 未找到")
};
}
var serviceType = service.GetType();
MethodInfo method = null;
// 查找匹配的方法
if (request.ParameterTypes != null && request.ParameterTypes.Length > 0) {
method = serviceType.GetMethod(request.MethodName, request.ParameterTypes);
} else {
// 如果没有提供参数类型,尝试按名称和参数数量匹配
var methods = serviceType.GetMethods().Where(m => m.Name == request.MethodName);
var paramCount = request.Parameters?.Length ?? 0;
method = methods.FirstOrDefault(m => m.GetParameters().Length == paramCount);
}
if (method == null) {
return new MethodCallResponse {
Exception = new IPCException($"方法 '{request.MethodName}' 在服务 '{request.ServiceName}' 中未找到")
};
}
// 调用方法
object result;
if (method.ReturnType == typeof(Task)) {
// 异步方法无返回值
var task = (Task)method.Invoke(service, request.Parameters);
await task;
result = null;
} else if (method.ReturnType.IsGenericType && method.ReturnType.GetGenericTypeDefinition() == typeof(Task<>)) {
// 异步方法有返回值
var task = (Task)method.Invoke(service, request.Parameters);
await task;
var resultProperty = task.GetType().GetProperty("Result");
result = resultProperty?.GetValue(task);
} else {
// 同步方法
result = method.Invoke(service, request.Parameters);
}
return new MethodCallResponse {
Result = result,
ResultType = method.ReturnType
};
} catch (TargetInvocationException ex) {
return new MethodCallResponse {
Exception = ex.InnerException ?? ex
};
} catch (Exception ex) {
return new MethodCallResponse {
Exception = ex
};
}
}
}
}