我使用 ASP.Net Core 获得了一个基本的 Web 应用程序,我在其中初始化了我的 SignalR 集线器。
集线器看起来像这样:
internal class SignalRTransceiverServer : Hub<ITransceiver<DataRecord, List<DataRecord>>>, ITransmitter<DataRecord>
{
public async Task SendDataPackage(DataRecord package)
{
Console.WriteLine(package);
try
{
await Clients.All.GetDataPackage(new List<DataRecord>() { package });
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
}
}
}
ITransceiver 接口如下所示:
public interface ITransceiver<T, R> : IReceiver<R>, ITransmitter<T>
{
}
虽然 IReceiver 有一个事件,应该被触发(对于客户端应用程序),但当新数据到达时:
public interface IReceiver<T>
{
/// <summary>
/// Gets a data package of <typeparamref name="T"/>. The parameter is for API's, which pass the arguments directly
/// (via RPC e.g.) into the method. Invokes the DataReceived event.
/// </summary>
/// <param name="package">An optional package parameter, if the underlaying mechanism needs to pass the data directly into
/// the function.</param>
public Task GetDataPackage(T? package);
public event EventHandler<T> DataReceived;
}
现在,当我尝试通过集线器上的 RPC 调用 GetDataPackage 方法时,它会抛出以下错误:
Microsoft.AspNetCore.SignalR.Internal.DefaultHubDispatcher[8]
Failed to invoke hub method 'SendDataPackage'.
System.InvalidOperationException: Type must not contain events.
at Microsoft.AspNetCore.SignalR.Internal.TypedClientBuilder`1.VerifyInterface(Type interfaceType)
at Microsoft.AspNetCore.SignalR.Internal.TypedClientBuilder`1.VerifyInterface(Type interfaceType)
at Microsoft.AspNetCore.SignalR.Internal.TypedClientBuilder`1.GenerateClientBuilder()
at System.Lazy`1.ViaFactory(LazyThreadSafetyMode mode)
--- End of stack trace from previous location ---
at System.Lazy`1.CreateValue()
at Microsoft.AspNetCore.SignalR.Internal.TypedClientBuilder`1.Build(IClientProxy proxy)
at TestHub.SignalRTransceiverServer.SendDataPackage(DataRecord package) in D:\dat.eE\Praktikum.RH\TestHub\SignalRTransceiverServer.cs:line 25
at Microsoft.AspNetCore.SignalR.Internal.DefaultHubDispatcher`1.ExecuteMethod(ObjectMethodExecutor methodExecutor, Hub hub, Object[] arguments)
at Microsoft.AspNetCore.SignalR.Internal.DefaultHubDispatcher`1.<Invoke>g__ExecuteInvocation|18_0(DefaultHubDispatcher`1 dispatcher, ObjectMethodExecutor methodExecutor, THub hub, Object[] arguments, AsyncServiceScope scope, IHubActivator`1 hubActivator, HubConnectionContext connection, HubMethodInvocationMessage hubMethodInvocationMessage, Boolean isStreamCall)
我的意思是我理解这个错误(只需删除 IReceiver 中的事件),但为什么 SignalR Core 不允许目标类型中的事件?如果可能的话,我怎样才能绕过它,同时仍然使用事件?
我找到了最简单的解决方法:只需使用普通的 Hub 类即可。
代替:
internal class SignalRTransceiverServer : Hub<ITransceiver<DataRecord, List<DataRecord>>>, ITransmitter<DataRecord>
以及具体的RPC调用与具体方法:
await Clients.All.GetDataPackage(new List<DataRecord>() { package });
我现在用:
internal class SignalRTransceiverServer : Hub, ITransmitter<DataRecord>
这会产生这样的 RPC:
await Clients.All.SendAsync("GetDataPackage", new List<DataRecord>() { package });
仍然有一个问题,为什么会这样。