SignalRServer improvements

This commit is contained in:
jozsef.b@aycode.com 2024-06-01 08:28:31 +02:00
parent 7f7a4f6ec1
commit 379ca61166
2 changed files with 70 additions and 42 deletions

View File

@ -153,14 +153,12 @@ namespace TIAMSharedUI.Shared.Components.Grids
SignalRClient.PostDataAsync(messageTag, dataItem, async repsonse => SignalRClient.PostDataAsync(messageTag, dataItem, async repsonse =>
{ {
if (repsonse.Status != SignalResponseStatus.Success || repsonse.ResponseData == null) if (repsonse.Status != SignalResponseStatus.Success || repsonse.ResponseData == null || !RefreshDataSourceItem(repsonse.ResponseData, isDelete))
{ {
RefreshDataSourceAsync().Forget(); RefreshDataSourceAsync().Forget();
return; return;
} }
RefreshDataSourceItem(repsonse.ResponseData, isDelete);
await OnDataSourceItemChanged.InvokeAsync(dataItem); await OnDataSourceItemChanged.InvokeAsync(dataItem);
await InvokeAsync(StateHasChanged); await InvokeAsync(StateHasChanged);
}).Forget(); }).Forget();
@ -168,8 +166,14 @@ namespace TIAMSharedUI.Shared.Components.Grids
//transfer = await devAdminSignalClient.PostDataAsync(SignalRTags.UpdateTransferAsync, transfer); //transfer = await devAdminSignalClient.PostDataAsync(SignalRTags.UpdateTransferAsync, transfer);
} }
public void RefreshDataSourceItem(TDataItem dataItem, bool isDelete, bool invokeItemChanged = true) public bool RefreshDataSourceItem(TDataItem dataItem, bool isDelete, bool invokeItemChanged = true)
{ {
if (dataItem.Id.IsNullOrEmpty())
{
Logger.Error($"dataItem.Id.IsNullOrEmpty()");
return false;
}
var transferIndex = _dataSource.FindIndex(x => x.Id == dataItem.Id); var transferIndex = _dataSource.FindIndex(x => x.Id == dataItem.Id);
if (isDelete && transferIndex > -1) _dataSource.RemoveAt(transferIndex); if (isDelete && transferIndex > -1) _dataSource.RemoveAt(transferIndex);
@ -178,6 +182,8 @@ namespace TIAMSharedUI.Shared.Components.Grids
if (transferIndex > -1) _dataSource[transferIndex] = dataItem; if (transferIndex > -1) _dataSource[transferIndex] = dataItem;
else _dataSource.Add(dataItem); else _dataSource.Add(dataItem);
} }
return true;
} }
protected override Task SetParametersAsyncCore(ParameterView parameters) protected override Task SetParametersAsyncCore(ParameterView parameters)

View File

@ -1,5 +1,6 @@
using System.Collections.Concurrent; using System.Collections.Concurrent;
using System.Reflection; using System.Reflection;
using System.Reflection.Emit;
using AyCode.Core.Extensions; using AyCode.Core.Extensions;
using AyCode.Core.Loggers; using AyCode.Core.Loggers;
using AyCode.Services.SignalRs; using AyCode.Services.SignalRs;
@ -41,16 +42,45 @@ public enum MethodParamType : byte
} }
[AttributeUsage(AttributeTargets.Method)] [AttributeUsage(AttributeTargets.Method)]
public class SignalRAttribute(int messageTag, MethodParamType methodParamType, Type paramType = null) : Attribute public class TagAttribute(int messageTag) : Attribute
{ {
public int MessageTag { get; init; } = messageTag; public int MessageTag { get; init; } = messageTag;
}
[AttributeUsage(AttributeTargets.Method)]
public class SignalRAttribute(int messageTag, MethodParamType methodParamType, Type paramType = null) : TagAttribute(messageTag)
{
public MethodParamType MethodParamType { get; init; } = methodParamType; public MethodParamType MethodParamType { get; init; } = methodParamType;
public Type ParamType { get; init; } = paramType; public Type ParamType { get; init; } = paramType;
} }
public class MethodInfoModel<TAttribute>(TAttribute attribute, MethodInfo methodInfo) where TAttribute : TagAttribute
{
public TAttribute Attribute { get; set; } = attribute;
public MethodInfo MethodInfo { get; set; } = methodInfo;
}
public class DynamicMethodCallModel<TAttribute> where TAttribute : TagAttribute
{
public object InstanceObject { get; init; }
public ConcurrentDictionary<int, MethodInfoModel<TAttribute>> MethodsByMessageTag { get; init; } = new();
public DynamicMethodCallModel(object instanceObject)
{
InstanceObject = instanceObject;
foreach (var methodInfo in instanceObject.GetType().GetMethods())
{
if (methodInfo.GetCustomAttribute(typeof(TAttribute)) is not TAttribute attribute) continue;
MethodsByMessageTag[attribute.MessageTag] = new MethodInfoModel<TAttribute>(attribute, methodInfo!);
}
}
}
public class DevAdminSignalRHub : Hub<ISignalRHubItemServer>, IAcSignalRHubServer public class DevAdminSignalRHub : Hub<ISignalRHubItemServer>, IAcSignalRHubServer
{ {
private readonly ConcurrentDictionary<object, ConcurrentDictionary<int, MethodInfo>> _methodsByMessageTag = new(); private readonly List<DynamicMethodCallModel<SignalRAttribute>> _dynamicMethodCallModels = new();
private readonly TIAM.Core.Loggers.Logger<DevAdminSignalRHub> _logger; private readonly TIAM.Core.Loggers.Logger<DevAdminSignalRHub> _logger;
private readonly AdminDal _adminDal; private readonly AdminDal _adminDal;
@ -62,25 +92,11 @@ public class DevAdminSignalRHub : Hub<ISignalRHubItemServer>, IAcSignalRHubServe
_adminDal = adminDal; _adminDal = adminDal;
_serviceProviderApiController = serviceProviderApiController; _serviceProviderApiController = serviceProviderApiController;
_transferDataApiController = transferDataApiController; _transferDataApiController = transferDataApiController;
_logger = new(logWriters.ToArray()); _logger = new(logWriters.ToArray());
var methods = typeof(ServiceProviderAPIController).GetMethods().Where(x => x.GetCustomAttributes(typeof(SignalRAttribute), false).Length > 0); _dynamicMethodCallModels.Add(new DynamicMethodCallModel<SignalRAttribute>(serviceProviderApiController));
_dynamicMethodCallModels.Add(new DynamicMethodCallModel<SignalRAttribute>(transferDataApiController));
_methodsByMessageTag[serviceProviderApiController] = new();
foreach (var methodInfo in methods)
{
var atr = methodInfo.GetCustomAttribute(typeof(SignalRAttribute)) as SignalRAttribute;
_methodsByMessageTag[serviceProviderApiController][atr.MessageTag] = methodInfo;
}
methods = typeof(TransferDataAPIController).GetMethods().Where(x => x.GetCustomAttributes(typeof(SignalRAttribute), false).Length > 0);
_methodsByMessageTag[transferDataApiController] = new();
foreach (var methodInfo in methods)
{
var atr = methodInfo.GetCustomAttribute(typeof(SignalRAttribute)) as SignalRAttribute;
_methodsByMessageTag[transferDataApiController][atr.MessageTag] = methodInfo;
}
} }
@ -121,32 +137,38 @@ public class DevAdminSignalRHub : Hub<ISignalRHubItemServer>, IAcSignalRHubServe
try try
{ {
foreach (var methodsByDeclaringObject in _methodsByMessageTag) foreach (var methodsByDeclaringObject in _dynamicMethodCallModels)
{ {
if (methodsByDeclaringObject.Value.TryGetValue(messageTag, out var methodInfo)) if (!methodsByDeclaringObject.MethodsByMessageTag.TryGetValue(messageTag, out var methodInfoModel)) continue;
{
var atr = methodInfo.GetCustomAttribute(typeof(SignalRAttribute)) as SignalRAttribute;
object[]? param = null;
if (atr.MethodParamType != MethodParamType.None) object[]? paramValues = null;
var parameters = methodInfoModel.MethodInfo.GetParameters();
logText = $"Found the dynamic method for the tag! tag: {messageTag}; method: {methodsByDeclaringObject.InstanceObject.GetType().Name}.{methodInfoModel.MethodInfo.Name}";
if (parameters.Length > 0)
{ {
param = new object[1]; _logger.Debug($"{logText}({parameters[0].ParameterType.Name})");
if (atr.MethodParamType == MethodParamType.Id)
paramValues = new object[1];
if (parameters[0].ParameterType == typeof(Guid) || parameters[0].ParameterType == typeof(Guid?))
{ {
param[0] = message!.MessagePackTo<SignalRequestByIdMessage>().Id; paramValues[0] = message!.MessagePackTo<SignalRequestByIdMessage>().Id;
} }
else else
{ {
var msg = message!.MessagePackTo<SignalPostJsonDataMessage<object>>(MessagePackSerializerOptions.Standard); var msg = message!.MessagePackTo<SignalPostJsonDataMessage<object>>(MessagePackSerializerOptions.Standard);
param[0] = msg.PostDataJson.JsonTo(atr.ParamType)!; paramValues[0] = msg.PostDataJson.JsonTo(parameters[0].ParameterType)!;
} }
} }
else _logger.Debug($"{logText}()");
await ResponseToCaller(messageTag, new SignalResponseJsonMessage(SignalResponseStatus.Success, methodInfo.InvokeMethod(methodsByDeclaringObject.Key, param)), requestId); await ResponseToCaller(messageTag, new SignalResponseJsonMessage(SignalResponseStatus.Success, methodInfoModel.MethodInfo.InvokeMethod(methodsByDeclaringObject.InstanceObject, paramValues)), requestId);
return; return;
} }
}
_logger.Debug($"Not found the dynamic method for the tag! tag: {messageTag};");
switch (messageTag) switch (messageTag)
{ {