cysharp / magiconion Goto Github PK
View Code? Open in Web Editor NEWUnified Realtime/API framework for .NET platform and Unity.
License: MIT License
Unified Realtime/API framework for .NET platform and Unity.
License: MIT License
Hi Neuecc,
I've been studying your UnityClient and the MagicUnion & MessagePack lib. They are awesome!
I have the grpc client hosted from a Unity 5 game (.Net 3.5) and it works great.
I have tried to host a grpc server from a Unity 5 game (.Net 3.5) and wonder if it is possible with your plugin libraries? Please, give your advises.
If it is possible, would you please give a basic instructions or guide lines or so. Very much appreciate it.
Thanks Neuecc.
How to solve this problem?
Hello,
I've faced an issue with the utile moc.exe. On its launch, with specified path to Sandbox.ConsoleServerDefinition.csproj there is generated file, that contain the following:
`
#pragma warning disable 618
#pragma warning disable 612
#pragma warning disable 414
#pragma warning disable 168
namespace MagicOnion
{
using global::System;
using global::System.Collections.Generic;
using global::System.Linq;
using global::MagicOnion;
using global::MagicOnion.Client;
public static partial class MagicOnionInitializer
{
static bool isRegistered = false;
[UnityEngine.RuntimeInitializeOnLoadMethod(UnityEngine.RuntimeInitializeLoadType.BeforeSceneLoad)]
public static void Register()
{
if(isRegistered) return;
isRegistered = true;
}
}
}
#pragma warning disable 618
#pragma warning disable 612
#pragma warning disable 414
#pragma warning disable 168
namespace MagicOnion.Resolvers
{
using System;
using MessagePack;
public class MagicOnionResolver : global::MessagePack.IFormatterResolver
{
public static readonly global::MessagePack.IFormatterResolver Instance = new MagicOnionResolver();
MagicOnionResolver()
{
}
public global::MessagePack.Formatters.IMessagePackFormatter<T> GetFormatter<T>()
{
return FormatterCache<T>.formatter;
}
static class FormatterCache<T>
{
public static readonly global::MessagePack.Formatters.IMessagePackFormatter<T> formatter;
static FormatterCache()
{
var f = MagicOnionResolverGetFormatterHelper.GetFormatter(typeof(T));
if (f != null)
{
formatter = (global::MessagePack.Formatters.IMessagePackFormatter<T>)f;
}
}
}
}
internal static class MagicOnionResolverGetFormatterHelper
{
static readonly global::System.Collections.Generic.Dictionary<Type, int> lookup;
static MagicOnionResolverGetFormatterHelper()
{
lookup = new global::System.Collections.Generic.Dictionary<Type, int>(0)
{
};
}
internal static object GetFormatter(Type t)
{
int key;
if (!lookup.TryGetValue(t, out key))
{
if (t == typeof(UniRx.Unit))
{
return MagicOnion.Resolvers.UniRxIntegrate.UnitFormatter.Instance;
}
else if (t == typeof(Nullable<UniRx.Unit>))
{
return MagicOnion.Resolvers.UniRxIntegrate.NullableUnitFormatter.Instance;
}
return null;
}
switch (key)
{
default: return null;
}
}
}
}
namespace MagicOnion.Resolvers.UniRxIntegrate
{
using System;
using UniRx;
using MessagePack;
using MessagePack.Formatters;
public class UnitFormatter : IMessagePackFormatter<Unit>
{
public static readonly IMessagePackFormatter<Unit> Instance = new UnitFormatter();
UnitFormatter()
{
}
public int Serialize(ref byte[] bytes, int offset, Unit value, IFormatterResolver typeResolver)
{
return MessagePackBinary.WriteNil(ref bytes, offset);
}
public Unit Deserialize(byte[] bytes, int offset, IFormatterResolver typeResolver, out int readSize)
{
if (bytes[offset] == MessagePackCode.Nil)
{
readSize = 1;
return Unit.Default;
}
else
{
throw new InvalidOperationException(string.Format("code is invalid. code:{0} format:{1}", bytes[offset], MessagePackCode.ToFormatName(bytes[offset])));
}
}
}
public class NullableUnitFormatter : IMessagePackFormatter<Unit?>
{
public static readonly IMessagePackFormatter<Unit?> Instance = new NullableUnitFormatter();
NullableUnitFormatter()
{
}
public int Serialize(ref byte[] bytes, int offset, Unit? value, IFormatterResolver typeResolver)
{
return MessagePackBinary.WriteNil(ref bytes, offset);
}
public Unit? Deserialize(byte[] bytes, int offset, IFormatterResolver typeResolver, out int readSize)
{
if (bytes[offset] == MessagePackCode.Nil)
{
readSize = 1;
return Unit.Default;
}
else
{
throw new InvalidOperationException(string.Format("code is invalid. code:{0} format:{1}", bytes[offset], MessagePackCode.ToFormatName(bytes[offset])));
}
}
}
}
#pragma warning disable 168
#pragma warning restore 414
#pragma warning restore 618
#pragma warning restore 612
`
So there is no declaration or implementation for interfaces that present in MagicOnionGenerated.cs
Could you please advise on how to use the utile moc.exe? If possible, on the example of your project so that it was clear which paths should be specified and so on.
Hi,
I have tried to run it in IOS and it fails with
dyld: lazy symbol binding failed: Symbol not found: _grpcsharp_redirect_log
in that function:
// System.Void Grpc.Core.Internal.NativeMethods/Delegates/grpcsharp_redirect_log_delegate::Invoke(Grpc.Core.Internal.GprLogDelegate)
extern "C" void grpcsharp_redirect_log_delegate_Invoke_m3963642216 (grpcsharp_redirect_log_delegate_t2162057115 * __this, GprLogDelegate_t430330606 * ___callback0, const MethodInfo* method)
{
if(__this->get_prev_9() != NULL)
{
grpcsharp_redirect_log_delegate_Invoke_m3963642216((grpcsharp_redirect_log_delegate_t2162057115 *)__this->get_prev_9(),___callback0, method);
}
il2cpp_codegen_raise_execution_engine_exception_if_method_is_not_found((MethodInfo*)(__this->get_method_3().get_m_value_0()));
bool ___methodIsStatic = MethodIsStatic((MethodInfo*)(__this->get_method_3().get_m_value_0()));
if (__this->get_m_target_2() != NULL && ___methodIsStatic)
{
typedef void (*FunctionPointerType) (Il2CppObject *, void* __this, GprLogDelegate_t430330606 * ___callback0, const MethodInfo* method);
((FunctionPointerType)__this->get_method_ptr_0())(NULL,__this->get_m_target_2(),___callback0,(MethodInfo*)(__this->get_method_3().get_m_value_0()));
}
else if (__this->get_m_target_2() != NULL || ___methodIsStatic)
{
typedef void (*FunctionPointerType) (void* __this, GprLogDelegate_t430330606 * ___callback0, const MethodInfo* method);
((FunctionPointerType)__this->get_method_ptr_0())(__this->get_m_target_2(),___callback0,(MethodInfo*)(__this->get_method_3().get_m_value_0()));
}
else
{
typedef void (*FunctionPointerType) (void* __this, const MethodInfo* method);
((FunctionPointerType)__this->get_method_ptr_0())(___callback0,(MethodInfo*)(__this->get_method_3().get_m_value_0()));
}
}
I wonder if I hasn't done some magic configuration on the Native dlls or something, but gRPC/Native/iOS/libgrpc_csharp_ext.a
and others there are configured to be included in IOS build...
MagicOnion.Server.StreamingContextRepository1.<WriteAsync>d__12
1.MoveNext() ,
Error sending from server
My company's new game - https://kuro-kishi.jp/ released in iOS/Android market on 28th, April.
Currently it receives 15,000 connections at peak time and it is growing.
Our system has two roles.
We're monitoring application metrics by Datadog.
I've created Datadog C# Client.
https://github.com/neuecc/DatadogSharp
I'll talk about this architecture at AWS Summit Tokyo 2017 on 2017-05-30~06-02.
http://www.awssummit.tokyo/
When talk is done, I'll upload translated presenation slide.
And of course, I will start working on .NET Standard and other improvements.
Can UnaryResult be Tasklike?
and BroadcastSelf.
I want to do some backoff stratergies at client, but it's confused me without a client interceptor, can you give some advice for implementing a client interceptor or any other ideas? thanks.
Hi,
Whats the preferred way to host Server? Can IIS be used to host MagicOnion Server or whats the preferred way.
Thanks
Hello. I am getting following exception when trying to connect to ChatService from Unity.
W1124 14:14:23.639783 Grpc.Core.Server Exception while handling RPC. System.IO.IOException: Error sending status from server.
at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw () [0x0000c] in /private/tmp/source-mono-d15-3/bockbuild-d15-3/profiles/mono-mac-xamarin/build-root/mono-x64/mcs/class/referencesource/mscorlib/system/runtime/exceptionservices/exceptionservicescommon.cs:151
at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess (System.Threading.Tasks.Task task) [0x00037] in /private/tmp/source-mono-d15-3/bockbuild-d15-3/profiles/mono-mac-xamarin/build-root/mono-x64/mcs/class/referencesource/mscorlib/system/runtime/compilerservices/TaskAwaiter.cs:187
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification (System.Threading.Tasks.Task task) [0x00028] in /private/tmp/source-mono-d15-3/bockbuild-d15-3/profiles/mono-mac-xamarin/build-root/mono-x64/mcs/class/referencesource/mscorlib/system/runtime/compilerservices/TaskAwaiter.cs:156
at System.Runtime.CompilerServices.TaskAwaiter.ValidateEnd (System.Threading.Tasks.Task task) [0x00008] in /private/tmp/source-mono-d15-3/bockbuild-d15-3/profiles/mono-mac-xamarin/build-root/mono-x64/mcs/class/referencesource/mscorlib/system/runtime/compilerservices/TaskAwaiter.cs:128
at System.Runtime.CompilerServices.ConfiguredTaskAwaitable+ConfiguredTaskAwaiter.GetResult () [0x00000] in /private/tmp/source-mono-d15-3/bockbuild-d15-3/profiles/mono-mac-xamarin/build-root/mono-x64/mcs/class/referencesource/mscorlib/system/runtime/compilerservices/TaskAwaiter.cs:447
at Grpc.Core.Internal.DuplexStreamingServerCallHandler`2+d__4[TRequest,TResponse].MoveNext () [0x00205] in <5ea8f8f676f3446d845f0b8ab846a51f>:0
--- End of stack trace from previous location where exception was thrown ---
at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw () [0x0000c] in /private/tmp/source-mono-d15-3/bockbuild-d15-3/profiles/mono-mac-xamarin/build-root/mono-x64/mcs/class/referencesource/mscorlib/system/runtime/exceptionservices/exceptionservicescommon.cs:151
at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess (System.Threading.Tasks.Task task) [0x00037] in /private/tmp/source-mono-d15-3/bockbuild-d15-3/profiles/mono-mac-xamarin/build-root/mono-x64/mcs/class/referencesource/mscorlib/system/runtime/compilerservices/TaskAwaiter.cs:187
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification (System.Threading.Tasks.Task task) [0x00028] in /private/tmp/source-mono-d15-3/bockbuild-d15-3/profiles/mono-mac-xamarin/build-root/mono-x64/mcs/class/referencesource/mscorlib/system/runtime/compilerservices/TaskAwaiter.cs:156
at System.Runtime.CompilerServices.TaskAwaiter.ValidateEnd (System.Threading.Tasks.Task task) [0x00008] in /private/tmp/source-mono-d15-3/bockbuild-d15-3/profiles/mono-mac-xamarin/build-root/mono-x64/mcs/class/referencesource/mscorlib/system/runtime/compilerservices/TaskAwaiter.cs:128
at System.Runtime.CompilerServices.ConfiguredTaskAwaitable+ConfiguredTaskAwaiter.GetResult () [0x00000] in /private/tmp/source-mono-d15-3/bockbuild-d15-3/profiles/mono-mac-xamarin/build-root/mono-x64/mcs/class/referencesource/mscorlib/system/runtime/compilerservices/TaskAwaiter.cs:447
At the same time console chat client from sandbox connects to server without issues. Can you give any advice on this?
Is MagicOnion technically not able to run on .NET Core ( or the 2.0 beta )?
Hi,
I was wondering if you can separate "gRPC for unity" part from MagicOnion as standalone github project. There is definitely a need for strong client side gRPC library for unity and yours is the only one that I've found.
I was planning to use only gRPC part so if it was standalone I would be able to contribute pull requests with potential bugfixes or help with upgrading to 1.1 etc
In any way thank you for lots of great high quality libraries around unity and dotnet core π
use NetGain? https://github.com/StackExchange/NetGain
When I implements IService In single Library, Then will throw a exception like issue title.
but I implements it in Server project. It's Successful.
I read souce code ,then find this code:
( code in MagicOnionEngine.cs of line 40)
/// <summary>
/// Search MagicOnion service from entry assembly.
/// </summary>
public static MagicOnionServiceDefinition BuildServerServiceDefinition(MagicOnionOptions options)
{
return BuildServerServiceDefinition(new[] { Assembly.GetEntryAssembly() }, options);
}
I think you'd better change Assembly.GetEntryAssembly to Assembly.GetExecutingAssembly
Hello. It will be really good if it will be possible to use DI for services.
For example this one https://autofac.org/
As I understand now it's not possible because services are created with Reflection instead of DI container.
Hey, really excited for this project!
Got several questions while testing out with Unity3D.
Wondering how to get "grpc_csharp_ext" native library work on iOS and Android. Since gRPC official c# native plugin only support win/linux/mac platform.
Thank you very much! =)
I am seeing seemingly random editor crash with such call stack:
0x00007FFF5879F7DB (ntdll) RtlpUnWaitCriticalSection
0x00007FFF587A0CE4 (ntdll) RtlEnterCriticalSection
0x00007FFF587A0C10 (ntdll) RtlEnterCriticalSection
0x00007FFF054A9BBD (grpc_csharp_ext) grpcsharp_test_nop
0x00007FFF0549568D (grpc_csharp_ext) grpcsharp_test_nop
0x00007FFF05491B35 (grpc_csharp_ext) grpcsharp_completion_queue_next
0x0000000036C73B3D (Mono JIT Code) (wrapper managed-to-native) Grpc.Core.Internal.NativeMethods/NativeCalls:grpcsharp_completion_queue_next (Grpc.Core.Internal.CompletionQueueSafeHandle)
0x0000000036C74A0D (Mono JIT Code) (wrapper delegate-invoke) Grpc.Core.Internal.NativeMethods/Delegates/grpcsharp_completion_queue_next_delegate:invoke_CompletionQueueEvent__this___CompletionQueueSafeHandle (Grpc.Core.Internal.CompletionQueueSafeHandle)
0x0000000036C72EC5 (Mono JIT Code) [C:\dev\SeedClient\Assets\Catapult\Network\gRPC\Core\Internal\CompletionQueueSafeHandle.cs:78] Grpc.Core.Internal.CompletionQueueSafeHandle:Next ()
0x0000000036C717B9 (Mono JIT Code) [C:\dev\SeedClient\Assets\Catapult\Network\gRPC\Core\Internal\GrpcThreadPool.cs:195] Grpc.Core.Internal.GrpcThreadPool:RunHandlerLoop (Grpc.Core.Internal.CompletionQueueSafeHandle,Grpc.Core.Profiling.IProfiler)
0x0000000036C715F6 (Mono JIT Code) [C:\dev\SeedClient\Assets\Catapult\Network\gRPC\Core\Internal\GrpcThreadPool.cs:173] Grpc.Core.Internal.GrpcThreadPool/<CreateAndStartThread>c__AnonStorey0:<>m__0 ()
0x0000000001F07392 (Mono JIT Code) (wrapper runtime-invoke) object:runtime_invoke_void__this__ (object,intptr,intptr,intptr)
0x00007FFF0B345703 (mono) [c:\buildslave\mono\build\mono\mini\mini.c:4937] mono_jit_runtime_invoke
0x00007FFF0B298425 (mono) [c:\buildslave\mono\build\mono\metadata\object.c:2623] mono_runtime_invoke
0x00007FFF0B2C36E7 (mono) [c:\buildslave\mono\build\mono\metadata\threads.c:721] start_wrapper
0x00007FFF0B3782D5 (mono) [c:\buildslave\mono\build\libgc\win32_threads.c:599] thread_start
0x00007FFF55F38364 (KERNEL32) BaseThreadInitThunk
0x00007FFF587D70D1 (ntdll) RtlUserThreadStart
It seems to be connected to recreating/disposing channels as I reproduce it when running such test code in a loop:
public IEnumerator TestPingPong()
{
for (int i = 0; i < 30; i++)
{
Log.Debug("Creating channel");
Channel channel = UnitTestClient.CreateChannel();
Log.Debug("Created channel");
var protocolSerialiser = new SeedProtocolSerializer();
var marshaller = Marshallers.Create<Message>(protocolSerialiser.ToBytes, protocolSerialiser.ToMessage);
var method = new Method<Message, Message>(MethodType.DuplexStreaming,
"x", "x", marshaller, marshaller);
var host = "localhost";
var caller = new EditorWindowSupportsCallInvoker(channel);
//var caller = new DefaultCallInvoker(channel);
using (var call = caller.AsyncDuplexStreamingCall(method, host,
new CallOptions(deadline: DateTime.UtcNow.AddSeconds(5))))
{
string data = "hello unity";
var request = new Ping() {Data = data}.AsMessage();
Log.Debug("calling service request:{$request}", request);
yield return call.RequestStream.WriteAsync(new Ping() {Data = data}.AsMessage())
.ToYieldInstruction();
var resultPromise = call.ResponseStream.AsObservable().Take(1).ToYieldInstruction();
yield return resultPromise;
resultPromise.HasResult.IsTrue();
var pong = resultPromise.Result as Message<Pong>;
Log.Debug("recieved reply:{reply}", pong);
pong.IsNotNull();
pong.Body.Data.Is(data + " back");
yield return call.RequestStream.CompleteAsync().ToYieldInstruction();
}
Log.Debug("Closing channel");
try
{
yield return channel.ShutdownAsync().ToYieldInstruction();
}
finally
{
Log.Debug("Closed channel");
}
}
}
It's definitely something to do with channel.ShutdownAsync()
because if you comment it out there is no crash
I was wondering if it's something you have seen before
Currently only use in StreamingHubFilter.
and BroadcastToSelf
I found that the TaskCancelException occurred every second when I built a new channel channel. After consulting GitHub, I learned that it was caused by the old version of Grpc design.
grpc/grpc#11328
grpc/grpc#13751
grpc/grpc#13227
Thanks.
MagicOnionOption, GroupConfiguration, controller lifecycle, exception handling between server and client,
ImmutableArrayGroup and ConcurrentDIctionaryGroup, How to use MagicOnion.Redis, etc.
At the moment many core MagicOnion classes on Unity side are coupled with MessagePack through statics. That makes it hard to use just some parts of framework. For example I am using just core bits with protobuf-net instead of MessagePack and my own server side framework, so every merge with upstream is total pain in places like ChannelContext.cs or MagicOnionClient.cs because of dependencies on MessagePack
I think it's great that MagicOnion comes in fully assembled opinionated package, but it would be even better if it was more layered and decoupled through interfaces allowing people to adapt or rewrite parts of it without hard fork and losing link with original repo
How to host on .NET Generic Host
and create middleware to easy to host.
How to solve this problem?
Hello,
Is your project support Universal Windows Platform with Unity3d?
I'm tried to use it in Unity Editor (2017.1.1) and it works fine, and build process from Unity to UWP Application goes fine without error. But when I tried to build UWP Project to get binaries I got several errors. ( Used IL2CPP Scripting Backend)
As a unity project, I used your unity3d sample from the repository.
Hi,
We have an issue with constant Unity freezes when you attach VS debugger.
I was wondering if that commit neucc/grpc fixes it?
Would it be possible for you please to update native binaries inside thise repo with the fixed version?
Thank you
and use Utf8Json instead of JSONNET
and improve string argument handling.
Not a significant thing, just for some curiosity...
If it is a intended behaviour, shouldn't sandbox sample client handle the exception from this status code?
Btw, It's really impressive work! I'd love to see it grow further. I'm going to play around the framework for some serious potential.
Hello,
found an issue on iOS device.
Here is a code from the file IFormatterResolver.cs:
public static IMessagePackFormatter<T> GetFormatterWithVerify<T>(this IFormatterResolver resolver)
{
IMessagePackFormatter<T> formatter;
try
{
formatter = resolver.GetFormatter<T>();
}
catch (TypeInitializationException ex)
{
Exception inner = ex;
while (inner.InnerException != null)
{
inner = inner.InnerException;
}
throw inner;
}
if (formatter == null)
{
throw new FormatterNotRegisteredException(typeof(T).FullName + " is not registered in this resolver. resolver:" + resolver.GetType().Name);
}
return formatter;
}
That calls an exception when trying to get an object from server response:
if (formatter == null)
{
throw new FormatterNotRegisteredException(typeof(T).FullName + " is not registered in this resolver. resolver:" + resolver.GetType().Name);
}
On other platforms everything works fine though.
Say, I want to check every call to the server that if StatusCode.Unauthenticated
is returned, I can popup a login window for the user.
How to do it correctly? Thanks!
The current HTTP/1 gateway has many overhead, it is only for develpment use, not for production.
I've created fast(est) JSON Serializer.
https://github.com/neuecc/Utf8Json
If MagiOnion becomes serialize to Json directly instead of MessagePack by option,
HTTP/1 gateway becomes faster and can be used gRPC for Web API like grpc-web, grpc-gateway.
We're using net framework 4.5 for our current project.We want to use grpc.MagicOnion can be used without update framework?
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using MagicOnion;
namespace FooServiceDefinition
{
public interface IMyFirstService : IService
{
UnaryResult SumAsync(int x, int y);
Task<UnaryResult> SumLegacyTaskAsync(int x, int y);
Task<ClientStreamingResult<int, string>> ClientStreamingSampleAsync();
Task<ServerStreamingResult> ServertSreamingSampleAsync(int x, int y, int z);
Task<DuplexStreamingResult<int, string>> DuplexStreamingSampleAync();
}
}
PS E:\Work\CSharpProject\Foo\FooServiceDefinition> .\moc.exe -i .\FooServiceDefinition.csproj -o .\Unity3d\Test.cs
Project Compilation Start:.\FooServiceDefinition.csproj
Project Compilation Complete:00:00:01.0242329
Method Collect Start
Method Collect Complete:00:00:00.0035521
Output Generation Start
[Out].\Unity3d\Test.cs
String Generation Complete:00:00:00.0095782
#pragma warning disable 618
#pragma warning disable 612
#pragma warning disable 414
#pragma warning disable 168
namespace MagicOnion
{
using global::System;
using global::System.Collections.Generic;
using global::System.Linq;
using global::MagicOnion;
using global::MagicOnion.Client;
public static partial class MagicOnionInitializer
{
static bool isRegistered = false;
[UnityEngine.RuntimeInitializeOnLoadMethod(UnityEngine.RuntimeInitializeLoadType.BeforeSceneLoad)]
public static void Register()
{
if(isRegistered) return;
isRegistered = true;
}
}
}
#pragma warning disable 618
#pragma warning disable 612
#pragma warning disable 414
#pragma warning disable 168
namespace MagicOnion.Resolvers
{
using System;
using MessagePack;
public class MagicOnionResolver : global::MessagePack.IFormatterResolver
{
public static readonly global::MessagePack.IFormatterResolver Instance = new MagicOnionResolver();
MagicOnionResolver()
{
}
public global::MessagePack.Formatters.IMessagePackFormatter<T> GetFormatter<T>()
{
return FormatterCache<T>.formatter;
}
static class FormatterCache<T>
{
public static readonly global::MessagePack.Formatters.IMessagePackFormatter<T> formatter;
static FormatterCache()
{
var f = MagicOnionResolverGetFormatterHelper.GetFormatter(typeof(T));
if (f != null)
{
formatter = (global::MessagePack.Formatters.IMessagePackFormatter<T>)f;
}
}
}
}
internal static class MagicOnionResolverGetFormatterHelper
{
static readonly global::System.Collections.Generic.Dictionary<Type, int> lookup;
static MagicOnionResolverGetFormatterHelper()
{
lookup = new global::System.Collections.Generic.Dictionary<Type, int>(0)
{
};
}
internal static object GetFormatter(Type t)
{
int key;
if (!lookup.TryGetValue(t, out key))
{
if (t == typeof(UniRx.Unit))
{
return MagicOnion.Resolvers.UniRxIntegrate.UnitFormatter.Instance;
}
else if (t == typeof(Nullable<UniRx.Unit>))
{
return MagicOnion.Resolvers.UniRxIntegrate.NullableUnitFormatter.Instance;
}
return null;
}
switch (key)
{
default: return null;
}
}
}
}
namespace MagicOnion.Resolvers.UniRxIntegrate
{
using System;
using UniRx;
using MessagePack;
using MessagePack.Formatters;
public class UnitFormatter : IMessagePackFormatter<Unit>
{
public static readonly IMessagePackFormatter<Unit> Instance = new UnitFormatter();
UnitFormatter()
{
}
public int Serialize(ref byte[] bytes, int offset, Unit value, IFormatterResolver typeResolver)
{
return MessagePackBinary.WriteNil(ref bytes, offset);
}
public Unit Deserialize(byte[] bytes, int offset, IFormatterResolver typeResolver, out int readSize)
{
if (bytes[offset] == MessagePackCode.Nil)
{
readSize = 1;
return Unit.Default;
}
else
{
throw new InvalidOperationException(string.Format("code is invalid. code:{0} format:{1}", bytes[offset], MessagePackCode.ToFormatName(bytes[offset])));
}
}
}
public class NullableUnitFormatter : IMessagePackFormatter<Unit?>
{
public static readonly IMessagePackFormatter<Unit?> Instance = new NullableUnitFormatter();
NullableUnitFormatter()
{
}
public int Serialize(ref byte[] bytes, int offset, Unit? value, IFormatterResolver typeResolver)
{
return MessagePackBinary.WriteNil(ref bytes, offset);
}
public Unit? Deserialize(byte[] bytes, int offset, IFormatterResolver typeResolver, out int readSize)
{
if (bytes[offset] == MessagePackCode.Nil)
{
readSize = 1;
return Unit.Default;
}
else
{
throw new InvalidOperationException(string.Format("code is invalid. code:{0} format:{1}", bytes[offset], MessagePackCode.ToFormatName(bytes[offset])));
}
}
}
}
#pragma warning disable 168
#pragma warning restore 414
#pragma warning restore 618
#pragma warning restore 612
I tried unity project generate but not working.
error messages to below.
environment
==============================================================
D:\library\Unity\MagicOnion\src\MagicOnion.CodeGenerator\bin\Debug\moc.exe --input=
GRPC-Client.csproj --output=Assets\Scripts\MagicOnion\MagicOnionGenerated.cs
Project Compilation Start:GRPC-Client.csproj
Project Compilation Complete:00:00:04.0922816
Method Collect Start
μ²λ¦¬λμ§ μμ μμΈ: System.Exception: Invalid Return Type, method:.cctor returnT
ype:void
μμΉ: MagicOnion.CodeAnalysis.MethodCollector.ExtractRequestResponseType(IMet
hodSymbol method, MethodType& methodType, String& requestType, String& responseT
ype, ITypeSymbol& unwrappedOriginalResponseType) νμΌ D:\library\Unity\MagicOnio
n\src\MagicOnion.CodeGenerator\CodeAnalysis\MethodCollector.cs:μ€ 187
μμΉ: MagicOnion.CodeAnalysis.MethodCollector.CreateMethodDefinition(IMethodS
ymbol y) νμΌ D:\library\Unity\MagicOnion\src\MagicOnion.CodeGenerator\CodeAnaly
sis\MethodCollector.cs:μ€ 123
μμΉ: System.Linq.Enumerable.WhereSelectEnumerableIterator2.MoveNext() μμΉ: System.Linq.Buffer
1..ctor(IEnumerable1 source) μμΉ: System.Linq.Enumerable.ToArray[TSource](IEnumerable
1 source)
μμΉ: MagicOnion.CodeAnalysis.MethodCollector.b__8_0(INamedTypeSymbol
x) νμΌ D:\library\Unity\MagicOnion\src\MagicOnion.CodeGenerator\CodeAnalysis\Me
thodCollector.cs:μ€ 73
μμΉ: System.Linq.Enumerable.WhereSelectArrayIterator2.MoveNext() μμΉ: System.Linq.Enumerable.<ConcatIterator>d__58
1.MoveNext()
μμΉ: System.Linq.Buffer1..ctor(IEnumerable
1 source)
μμΉ: System.Linq.Enumerable.ToArray[TSource](IEnumerable`1 source)
μμΉ: MagicOnion.CodeAnalysis.MethodCollector.Visit() νμΌ D:\library\Unity\M
agicOnion\src\MagicOnion.CodeGenerator\CodeAnalysis\MethodCollector.cs:μ€ 72
μμΉ: MagicOnion.CodeGenerator.Program.Main(String[] args) νμΌ D:\library\Un
ity\MagicOnion\src\MagicOnion.CodeGenerator\Program.cs:μ€ 93
A declarative, efficient, and flexible JavaScript library for building user interfaces.
π Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. πππ
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google β€οΈ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.