Aetheria/Assets/Scripts/MagicOnion/Server/Hubs/BroadcasterHelper.cs
hyperion51 a0c8dbee72 Initial Client/Server Communication
#1
Followed the MagicOnion quickstart guide, borrowing code from the chat sample app to get something working
2020-02-26 17:48:40 +00:00

94 lines
No EOL
3.4 KiB
C#

using MagicOnion.Utils;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Threading.Tasks;
namespace MagicOnion.Server.Hubs
{
public static class BroadcasterHelper
{
internal static readonly Type[] dynamicArgumentTupleTypes = typeof(DynamicArgumentTuple<,>).GetTypeInfo().Assembly
.GetTypes()
.Where(x => x.Name.StartsWith("DynamicArgumentTuple") && !x.Name.Contains("Formatter"))
.OrderBy(x => x.GetGenericArguments().Length)
.ToArray();
internal static MethodDefinition[] SearchDefinitions(Type interfaceType)
{
return interfaceType
.GetInterfaces()
.Concat(new[] { interfaceType })
.SelectMany(x => x.GetMethods())
.Where(x =>
{
var methodInfo = x;
if (methodInfo.IsSpecialName && (methodInfo.Name.StartsWith("set_") || methodInfo.Name.StartsWith("get_"))) return false;
if (methodInfo.GetCustomAttribute<IgnoreAttribute>(false) != null) return false; // ignore
var methodName = methodInfo.Name;
if (methodName == "Equals"
|| methodName == "GetHashCode"
|| methodName == "GetType"
|| methodName == "ToString"
)
{
return false;
}
return true;
})
.Where(x => !x.IsSpecialName)
.Select(x => new MethodDefinition
{
ReceiverType = interfaceType,
MethodInfo = x,
})
.ToArray();
}
internal static void VerifyMethodDefinitions(MethodDefinition[] definitions)
{
// define and set.
var map = new Dictionary<int, MethodDefinition>(definitions.Length);
foreach (var item in definitions)
{
var methodId = item.MethodInfo.GetCustomAttribute<MethodIdAttribute>()?.MethodId ?? FNV1A32.GetHashCode(item.MethodInfo.Name);
if (map.ContainsKey(methodId))
{
throw new Exception($"TReceiver does not allows duplicate methodId(hash code). Please change name or use MethodIdAttribute. {map[methodId].MethodInfo.Name} and {item.MethodInfo.Name}");
}
map.Add(methodId, item);
if (!(item.MethodInfo.ReturnType == typeof(void)))
{
throw new Exception($"Invalid definition, TReceiver's return type must only be `void`. {item.MethodInfo.Name}.");
}
item.MethodId = methodId;
}
}
public static async void FireAndForget(Task task)
{
try
{
await task.ConfigureAwait(false);
}
catch(Exception ex)
{
Grpc.Core.GrpcEnvironment.Logger?.Error(ex, "exception occured in client broadcast.");
}
}
internal class MethodDefinition
{
public string Path => ReceiverType.Name + "/" + MethodInfo.Name;
public Type ReceiverType;
public MethodInfo MethodInfo;
public int MethodId;
}
}
}