コード例 #1
0
        static void VerifyMethodDefinitions(MethodDefinition[] definitions)
        {
            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($"TStreamingHub 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.IsGenericType && item.MethodInfo.ReturnType.GetGenericTypeDefinition() == typeof(Task <>)) &&
                    item.MethodInfo.ReturnType != typeof(Task))
                {
                    throw new Exception($"Invalid definition, TStreamingHub's return type must only be `Task` or `Task<T>`. {item.MethodInfo.Name}.");
                }

                item.MethodId = methodId;
                if (item.RequestType == null)
                {
                    item.RequestType = MagicOnionMarshallers.CreateRequestType(item.MethodInfo.GetParameters());
                }
            }
        }
コード例 #2
0
        static IMyFirstServiceClient()
        {
            SumAsyncMethod             = new Method <byte[], byte[]>(MethodType.Unary, "IMyFirstService", "SumAsync", MagicOnionMarshallers.ByteArrayMarshaller, MagicOnionMarshallers.ByteArrayMarshaller);
            SumAsyncRequestMarshaller  = MagicOnionMarshallers.CreateZeroFormatterMarshaller(new DynamicArgumentTupleFormatter <ZeroFormatter.Formatters.DefaultResolver, int, int>(default(int), default(int)));
            SumAsyncResponseMarshaller = MagicOnionMarshallers.CreateZeroFormatterMarshaller(Formatter <ZeroFormatter.Formatters.DefaultResolver, string> .Default);

            SumAsync2Method             = new Method <byte[], byte[]>(MethodType.Unary, "IMyFirstService", "SumAsync2", MagicOnionMarshallers.ByteArrayMarshaller, MagicOnionMarshallers.ByteArrayMarshaller);
            SumAsync2RequestMarshaller  = MagicOnionMarshallers.CreateZeroFormatterMarshaller(new DynamicArgumentTupleFormatter <ZeroFormatter.Formatters.DefaultResolver, int, int>(default(int), default(int)));
            SumAsync2ResponseMarshaller = MagicOnionMarshallers.CreateZeroFormatterMarshaller(Formatter <ZeroFormatter.Formatters.DefaultResolver, string> .Default);

            StreamingOneMethod             = new Method <byte[], byte[]>(MethodType.ClientStreaming, "IMyFirstService", "StreamingOne", MagicOnionMarshallers.ByteArrayMarshaller, MagicOnionMarshallers.ByteArrayMarshaller);
            StreamingOneRequestMarshaller  = MagicOnionMarshallers.CreateZeroFormatterMarshaller(ZeroFormatter.Formatters.Formatter <ZeroFormatter.Formatters.DefaultResolver, int> .Default);
            StreamingOneResponseMarshaller = MagicOnionMarshallers.CreateZeroFormatterMarshaller(Formatter <ZeroFormatter.Formatters.DefaultResolver, string> .Default);

            StreamingTwoMethod             = new Method <byte[], byte[]>(MethodType.ServerStreaming, "IMyFirstService", "StreamingTwo", MagicOnionMarshallers.ByteArrayMarshaller, MagicOnionMarshallers.ByteArrayMarshaller);
            StreamingTwoRequestMarshaller  = MagicOnionMarshallers.CreateZeroFormatterMarshaller(new DynamicArgumentTupleFormatter <ZeroFormatter.Formatters.DefaultResolver, int, int, int>(default(int), default(int), default(int)));
            StreamingTwoResponseMarshaller = MagicOnionMarshallers.CreateZeroFormatterMarshaller(Formatter <ZeroFormatter.Formatters.DefaultResolver, string> .Default);

            StreamingTwo2Method             = new Method <byte[], byte[]>(MethodType.ServerStreaming, "IMyFirstService", "StreamingTwo2", MagicOnionMarshallers.ByteArrayMarshaller, MagicOnionMarshallers.ByteArrayMarshaller);
            StreamingTwo2RequestMarshaller  = MagicOnionMarshallers.CreateZeroFormatterMarshaller(new DynamicArgumentTupleFormatter <ZeroFormatter.Formatters.DefaultResolver, int, int, int>(default(int), default(int), 9999));
            StreamingTwo2ResponseMarshaller = MagicOnionMarshallers.CreateZeroFormatterMarshaller(Formatter <ZeroFormatter.Formatters.DefaultResolver, string> .Default);

            StreamingThreeMethod             = new Method <byte[], byte[]>(MethodType.DuplexStreaming, "IMyFirstService", "StreamingThree", MagicOnionMarshallers.ByteArrayMarshaller, MagicOnionMarshallers.ByteArrayMarshaller);
            StreamingThreeRequestMarshaller  = MagicOnionMarshallers.CreateZeroFormatterMarshaller(ZeroFormatter.Formatters.Formatter <ZeroFormatter.Formatters.DefaultResolver, int> .Default);
            StreamingThreeResponseMarshaller = MagicOnionMarshallers.CreateZeroFormatterMarshaller(Formatter <ZeroFormatter.Formatters.DefaultResolver, string> .Default);
        }
コード例 #3
0
        static IHeartbeatClient()
        {
            ConnectMethod             = new Method <byte[], byte[]>(MethodType.DuplexStreaming, "IHeartbeat", "Connect", MagicOnionMarshallers.ByteArrayMarshaller, MagicOnionMarshallers.ByteArrayMarshaller);
            ConnectRequestMarshaller  = MagicOnionMarshallers.CreateZeroFormatterMarshaller(ZeroFormatter.Formatters.Formatter <ZeroFormatter.Formatters.DefaultResolver, global::SharedLibrary.Nil> .Default);
            ConnectResponseMarshaller = MagicOnionMarshallers.CreateZeroFormatterMarshaller(Formatter <ZeroFormatter.Formatters.DefaultResolver, global::SharedLibrary.Nil> .Default);

            TestSendMethod             = new Method <byte[], byte[]>(MethodType.Unary, "IHeartbeat", "TestSend", MagicOnionMarshallers.ByteArrayMarshaller, MagicOnionMarshallers.ByteArrayMarshaller);
            TestSendRequestMarshaller  = MagicOnionMarshallers.CreateZeroFormatterMarshaller(ZeroFormatter.Formatters.Formatter <ZeroFormatter.Formatters.DefaultResolver, string> .Default);
            TestSendResponseMarshaller = MagicOnionMarshallers.CreateZeroFormatterMarshaller(Formatter <ZeroFormatter.Formatters.DefaultResolver, global::SharedLibrary.Nil> .Default);
        }
コード例 #4
0
        static void DefineStaticFields(TypeBuilder typeBuilder, MethodDefinition[] definitions)
        {
            foreach (var item in definitions)
            {
                item.FieldMethod  = typeBuilder.DefineField(item.MethodInfo.Name + "Method", bytesMethod, FieldAttributes.Private | FieldAttributes.Static);
                item.ResponseType = UnwrapResponseType(item, out item.MethodType, out item.ResponseIsTask, out item.RequestType);

                if (item.RequestType == null)
                {
                    item.RequestType = MagicOnionMarshallers.CreateRequestType(item.MethodInfo.GetParameters());
                }
            }
        }
コード例 #5
0
        static IArgumentPatternClient()
        {
            Unary1Method             = new Method <byte[], byte[]>(MethodType.Unary, "IArgumentPattern", "Unary1", MagicOnionMarshallers.ByteArrayMarshaller, MagicOnionMarshallers.ByteArrayMarshaller);
            Unary1RequestMarshaller  = MagicOnionMarshallers.CreateZeroFormatterMarshaller(new DynamicArgumentTupleFormatter <ZeroFormatter.Formatters.DefaultResolver, int, int, string, global::SharedLibrary.MyEnum, global::SharedLibrary.MyStructResponse, ulong, global::SharedLibrary.MyRequest>(default(int), default(int), "unknown", SharedLibrary.MyEnum.Orange, default(global::SharedLibrary.MyStructResponse), 9, null));
            Unary1ResponseMarshaller = MagicOnionMarshallers.CreateZeroFormatterMarshaller(Formatter <ZeroFormatter.Formatters.DefaultResolver, global::SharedLibrary.MyHugeResponse> .Default);

            Unary2Method             = new Method <byte[], byte[]>(MethodType.Unary, "IArgumentPattern", "Unary2", MagicOnionMarshallers.ByteArrayMarshaller, MagicOnionMarshallers.ByteArrayMarshaller);
            Unary2RequestMarshaller  = MagicOnionMarshallers.CreateZeroFormatterMarshaller(ZeroFormatter.Formatters.Formatter <ZeroFormatter.Formatters.DefaultResolver, global::SharedLibrary.MyRequest> .Default);
            Unary2ResponseMarshaller = MagicOnionMarshallers.CreateZeroFormatterMarshaller(Formatter <ZeroFormatter.Formatters.DefaultResolver, global::SharedLibrary.MyResponse> .Default);

            Unary3Method             = new Method <byte[], byte[]>(MethodType.Unary, "IArgumentPattern", "Unary3", MagicOnionMarshallers.ByteArrayMarshaller, MagicOnionMarshallers.ByteArrayMarshaller);
            Unary3RequestMarshaller  = MagicOnionMarshallers.CreateZeroFormatterMarshaller(ZeroFormatter.Formatters.Formatter <ZeroFormatter.Formatters.DefaultResolver, byte[]> .Default);
            Unary3ResponseMarshaller = MagicOnionMarshallers.CreateZeroFormatterMarshaller(Formatter <ZeroFormatter.Formatters.DefaultResolver, global::SharedLibrary.MyResponse> .Default);

            Unary5Method             = new Method <byte[], byte[]>(MethodType.Unary, "IArgumentPattern", "Unary5", MagicOnionMarshallers.ByteArrayMarshaller, MagicOnionMarshallers.ByteArrayMarshaller);
            Unary5RequestMarshaller  = MagicOnionMarshallers.CreateZeroFormatterMarshaller(ZeroFormatter.Formatters.Formatter <ZeroFormatter.Formatters.DefaultResolver, global::SharedLibrary.MyStructRequest> .Default);
            Unary5ResponseMarshaller = MagicOnionMarshallers.CreateZeroFormatterMarshaller(Formatter <ZeroFormatter.Formatters.DefaultResolver, global::SharedLibrary.MyStructResponse> .Default);

            ServerStreamingResult1Method             = new Method <byte[], byte[]>(MethodType.ServerStreaming, "IArgumentPattern", "ServerStreamingResult1", MagicOnionMarshallers.ByteArrayMarshaller, MagicOnionMarshallers.ByteArrayMarshaller);
            ServerStreamingResult1RequestMarshaller  = MagicOnionMarshallers.CreateZeroFormatterMarshaller(new DynamicArgumentTupleFormatter <ZeroFormatter.Formatters.DefaultResolver, int, int, string>(default(int), default(int), "unknown"));
            ServerStreamingResult1ResponseMarshaller = MagicOnionMarshallers.CreateZeroFormatterMarshaller(Formatter <ZeroFormatter.Formatters.DefaultResolver, global::SharedLibrary.MyResponse> .Default);

            ServerStreamingResult2Method             = new Method <byte[], byte[]>(MethodType.ServerStreaming, "IArgumentPattern", "ServerStreamingResult2", MagicOnionMarshallers.ByteArrayMarshaller, MagicOnionMarshallers.ByteArrayMarshaller);
            ServerStreamingResult2RequestMarshaller  = MagicOnionMarshallers.CreateZeroFormatterMarshaller(ZeroFormatter.Formatters.Formatter <ZeroFormatter.Formatters.DefaultResolver, global::SharedLibrary.MyRequest> .Default);
            ServerStreamingResult2ResponseMarshaller = MagicOnionMarshallers.CreateZeroFormatterMarshaller(Formatter <ZeroFormatter.Formatters.DefaultResolver, global::SharedLibrary.MyResponse> .Default);

            ServerStreamingResult3Method             = new Method <byte[], byte[]>(MethodType.ServerStreaming, "IArgumentPattern", "ServerStreamingResult3", MagicOnionMarshallers.ByteArrayMarshaller, MagicOnionMarshallers.ByteArrayMarshaller);
            ServerStreamingResult3RequestMarshaller  = MagicOnionMarshallers.CreateZeroFormatterMarshaller(ZeroFormatter.Formatters.Formatter <ZeroFormatter.Formatters.DefaultResolver, byte[]> .Default);
            ServerStreamingResult3ResponseMarshaller = MagicOnionMarshallers.CreateZeroFormatterMarshaller(Formatter <ZeroFormatter.Formatters.DefaultResolver, global::SharedLibrary.MyResponse> .Default);

            ServerStreamingResult4Method             = new Method <byte[], byte[]>(MethodType.ServerStreaming, "IArgumentPattern", "ServerStreamingResult4", MagicOnionMarshallers.ByteArrayMarshaller, MagicOnionMarshallers.ByteArrayMarshaller);
            ServerStreamingResult4RequestMarshaller  = MagicOnionMarshallers.CreateZeroFormatterMarshaller(ZeroFormatter.Formatters.Formatter <ZeroFormatter.Formatters.DefaultResolver, byte[]> .Default);
            ServerStreamingResult4ResponseMarshaller = MagicOnionMarshallers.CreateZeroFormatterMarshaller(Formatter <ZeroFormatter.Formatters.DefaultResolver, global::SharedLibrary.Nil> .Default);

            ServerStreamingResult5Method             = new Method <byte[], byte[]>(MethodType.ServerStreaming, "IArgumentPattern", "ServerStreamingResult5", MagicOnionMarshallers.ByteArrayMarshaller, MagicOnionMarshallers.ByteArrayMarshaller);
            ServerStreamingResult5RequestMarshaller  = MagicOnionMarshallers.CreateZeroFormatterMarshaller(ZeroFormatter.Formatters.Formatter <ZeroFormatter.Formatters.DefaultResolver, global::SharedLibrary.MyStructRequest> .Default);
            ServerStreamingResult5ResponseMarshaller = MagicOnionMarshallers.CreateZeroFormatterMarshaller(Formatter <ZeroFormatter.Formatters.DefaultResolver, global::SharedLibrary.MyStructResponse> .Default);

            UnaryS1Method             = new Method <byte[], byte[]>(MethodType.Unary, "IArgumentPattern", "UnaryS1", MagicOnionMarshallers.ByteArrayMarshaller, MagicOnionMarshallers.ByteArrayMarshaller);
            UnaryS1RequestMarshaller  = MagicOnionMarshallers.CreateZeroFormatterMarshaller(new DynamicArgumentTupleFormatter <ZeroFormatter.Formatters.DefaultResolver, global::System.DateTime, global::System.DateTimeOffset>(default(global::System.DateTime), default(global::System.DateTimeOffset)));
            UnaryS1ResponseMarshaller = MagicOnionMarshallers.CreateZeroFormatterMarshaller(Formatter <ZeroFormatter.Formatters.DefaultResolver, bool> .Default);

            UnaryS2Method             = new Method <byte[], byte[]>(MethodType.Unary, "IArgumentPattern", "UnaryS2", MagicOnionMarshallers.ByteArrayMarshaller, MagicOnionMarshallers.ByteArrayMarshaller);
            UnaryS2RequestMarshaller  = MagicOnionMarshallers.CreateZeroFormatterMarshaller(ZeroFormatter.Formatters.Formatter <ZeroFormatter.Formatters.DefaultResolver, int[]> .Default);
            UnaryS2ResponseMarshaller = MagicOnionMarshallers.CreateZeroFormatterMarshaller(Formatter <ZeroFormatter.Formatters.DefaultResolver, bool> .Default);

            UnaryS3Method             = new Method <byte[], byte[]>(MethodType.Unary, "IArgumentPattern", "UnaryS3", MagicOnionMarshallers.ByteArrayMarshaller, MagicOnionMarshallers.ByteArrayMarshaller);
            UnaryS3RequestMarshaller  = MagicOnionMarshallers.CreateZeroFormatterMarshaller(new DynamicArgumentTupleFormatter <ZeroFormatter.Formatters.DefaultResolver, int[], string[], global::SharedLibrary.MyEnum[]>(default(int[]), default(string[]), default(global::SharedLibrary.MyEnum[])));
            UnaryS3ResponseMarshaller = MagicOnionMarshallers.CreateZeroFormatterMarshaller(Formatter <ZeroFormatter.Formatters.DefaultResolver, bool> .Default);
        }
コード例 #6
0
            public UnaryResult <MyResponse> Unary1(int x, int y, string z = "unknown")
            {
                var tuple             = new DynamicArgumentTuple <int, int>(x, y);
                var formatter         = new DynamicArgumentTupleFormatter <DefaultResolver, int, int>(0, 0);
                var requestMarshaller = MagicOnionMarshallers.CreateZeroFormatterMarshaller(formatter);

                var method = new Method <byte[], byte[]>(MethodType.Unary, "IArgumentPattern", "Unary1", MagicOnionMarshallers.ByteArrayMarshaller, MagicOnionMarshallers.ByteArrayMarshaller);

                var request    = requestMarshaller.Serializer(tuple);
                var callResult = invoker.AsyncUnaryCall(method, null, default(CallOptions), request);

                var responseMarshaller = MagicOnionMarshallers.CreateZeroFormatterMarshaller(ZeroFormatter.Formatters.Formatter <DefaultResolver, MyResponse> .Default);

                return(new UnaryResult <MyResponse>(callResult, responseMarshaller));
            }
コード例 #7
0
        static IStandardClient()
        {
            Unary1AsyncMethod             = new Method <byte[], byte[]>(MethodType.Unary, "IStandard", "Unary1Async", MagicOnionMarshallers.ByteArrayMarshaller, MagicOnionMarshallers.ByteArrayMarshaller);
            Unary1AsyncRequestMarshaller  = MagicOnionMarshallers.CreateZeroFormatterMarshaller(new DynamicArgumentTupleFormatter <ZeroFormatter.Formatters.DefaultResolver, int, int>(default(int), default(int)));
            Unary1AsyncResponseMarshaller = MagicOnionMarshallers.CreateZeroFormatterMarshaller(Formatter <ZeroFormatter.Formatters.DefaultResolver, int> .Default);

            ClientStreaming1AsyncMethod             = new Method <byte[], byte[]>(MethodType.ClientStreaming, "IStandard", "ClientStreaming1Async", MagicOnionMarshallers.ByteArrayMarshaller, MagicOnionMarshallers.ByteArrayMarshaller);
            ClientStreaming1AsyncRequestMarshaller  = MagicOnionMarshallers.CreateZeroFormatterMarshaller(ZeroFormatter.Formatters.Formatter <ZeroFormatter.Formatters.DefaultResolver, int> .Default);
            ClientStreaming1AsyncResponseMarshaller = MagicOnionMarshallers.CreateZeroFormatterMarshaller(Formatter <ZeroFormatter.Formatters.DefaultResolver, string> .Default);

            ServerStreamingAsyncMethod             = new Method <byte[], byte[]>(MethodType.ServerStreaming, "IStandard", "ServerStreamingAsync", MagicOnionMarshallers.ByteArrayMarshaller, MagicOnionMarshallers.ByteArrayMarshaller);
            ServerStreamingAsyncRequestMarshaller  = MagicOnionMarshallers.CreateZeroFormatterMarshaller(new DynamicArgumentTupleFormatter <ZeroFormatter.Formatters.DefaultResolver, int, int, int>(default(int), default(int), default(int)));
            ServerStreamingAsyncResponseMarshaller = MagicOnionMarshallers.CreateZeroFormatterMarshaller(Formatter <ZeroFormatter.Formatters.DefaultResolver, int> .Default);

            DuplexStreamingAsyncMethod             = new Method <byte[], byte[]>(MethodType.DuplexStreaming, "IStandard", "DuplexStreamingAsync", MagicOnionMarshallers.ByteArrayMarshaller, MagicOnionMarshallers.ByteArrayMarshaller);
            DuplexStreamingAsyncRequestMarshaller  = MagicOnionMarshallers.CreateZeroFormatterMarshaller(ZeroFormatter.Formatters.Formatter <ZeroFormatter.Formatters.DefaultResolver, int> .Default);
            DuplexStreamingAsyncResponseMarshaller = MagicOnionMarshallers.CreateZeroFormatterMarshaller(Formatter <ZeroFormatter.Formatters.DefaultResolver, int> .Default);
        }
コード例 #8
0
        public StreamingHubHandler(Type classType, MethodInfo methodInfo, StreamingHubHandlerOptions handlerOptions, IServiceProvider serviceProvider)
        {
            var hubInterface    = classType.GetInterfaces().First(x => x.GetTypeInfo().IsGenericType&& x.GetGenericTypeDefinition() == typeof(IStreamingHub <,>)).GetGenericArguments()[0];
            var interfaceMethod = GetInterfaceMethod(classType, hubInterface, methodInfo.Name);

            this.serviceProvider = serviceProvider;

            this.HubType    = classType;
            this.HubName    = hubInterface.Name;
            this.MethodInfo = methodInfo;
            // Validation for Id
            if (methodInfo.GetCustomAttribute <MethodIdAttribute>() != null)
            {
                throw new InvalidOperationException($"Hub Implementation can not add [MethodId], you should add hub `interface`. {classType.Name}/{methodInfo.Name}");
            }
            this.MethodId = interfaceMethod.GetCustomAttribute <MethodIdAttribute>()?.MethodId ?? FNV1A32.GetHashCode(interfaceMethod.Name);

            this.UnwrappedResponseType = UnwrapResponseType(methodInfo);

            var resolver   = handlerOptions.SerializerOptions.Resolver;
            var parameters = methodInfo.GetParameters();

            this.RequestType = MagicOnionMarshallers.CreateRequestTypeAndSetResolver(classType.Name + "/" + methodInfo.Name, parameters, ref resolver);

            this.serializerOptions = handlerOptions.SerializerOptions.WithResolver(resolver);

            this.AttributeLookup = classType.GetCustomAttributes(true)
                                   .Concat(methodInfo.GetCustomAttributes(true))
                                   .Cast <Attribute>()
                                   .ToLookup(x => x.GetType());

            this.filters = handlerOptions.GlobalStreamingHubFilters
                           .OfType <IMagicOnionFilterFactory <StreamingHubFilterAttribute> >()
                           .Concat(classType.GetCustomAttributes <StreamingHubFilterAttribute>(true).Select(x => new StreamingHubFilterDescriptor(x, x.Order)))
                           .Concat(classType.GetCustomAttributes(true).OfType <IMagicOnionFilterFactory <StreamingHubFilterAttribute> >())
                           .Concat(methodInfo.GetCustomAttributes <StreamingHubFilterAttribute>(true).Select(x => new StreamingHubFilterDescriptor(x, x.Order)))
                           .Concat(methodInfo.GetCustomAttributes(true).OfType <IMagicOnionFilterFactory <StreamingHubFilterAttribute> >())
                           .OrderBy(x => x.Order)
                           .ToArray();

            // validation filter
            if (methodInfo.GetCustomAttribute <MagicOnionFilterAttribute>(true) != null)
            {
                throw new InvalidOperationException($"StreamingHub method can not add [MagicOnionFilter], you should add [StreamingHubFilter]. {classType.Name}/{methodInfo.Name}");
            }

            this.toStringCache    = HubName + "/" + MethodInfo.Name;
            this.getHashCodeCache = HubName.GetHashCode() ^ MethodInfo.Name.GetHashCode() << 2;

            // ValueTask (StreamingHubContext context) =>
            // {
            //    T request = LZ4MessagePackSerializer.Deserialize<T>(context.Request, context.FormatterResolver);
            //    Task<T> result = ((HubType)context.HubInstance).Foo(request);
            //    return WriteInAsyncLockInTaskWithMessageId(result) || return new ValueTask(result)
            // }
            try
            {
                var flags = BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic;

                var contextArg           = Expression.Parameter(typeof(StreamingHubContext), "context");
                var requestArg           = Expression.Parameter(RequestType, "request");
                var getSerializerOptions = Expression.Property(contextArg, typeof(StreamingHubContext).GetProperty("SerializerOptions", flags) !);
                var contextRequest       = Expression.Property(contextArg, typeof(StreamingHubContext).GetProperty("Request", flags) !);
                var noneCancellation     = Expression.Default(typeof(CancellationToken));
                var getInstanceCast      = Expression.Convert(Expression.Property(contextArg, typeof(StreamingHubContext).GetProperty("HubInstance", flags) !), HubType);

                var callDeserialize = Expression.Call(messagePackDeserialize.MakeGenericMethod(RequestType), contextRequest, getSerializerOptions, noneCancellation);
                var assignRequest   = Expression.Assign(requestArg, callDeserialize);

                Expression[] arguments = new Expression[parameters.Length];
                if (parameters.Length == 1)
                {
                    arguments[0] = requestArg;
                }
                else
                {
                    for (int i = 0; i < parameters.Length; i++)
                    {
                        arguments[i] = Expression.Field(requestArg, "Item" + (i + 1));
                    }
                }

                var callBody = Expression.Call(getInstanceCast, methodInfo, arguments);

                var finalMethod = (methodInfo.ReturnType.IsGenericType)
                    ? typeof(StreamingHubContext).GetMethod(nameof(StreamingHubContext.WriteResponseMessage), flags) !.MakeGenericMethod(UnwrappedResponseType !)
                    : typeof(StreamingHubContext).GetMethod(nameof(StreamingHubContext.WriteResponseMessageNil), flags) !;
                callBody = Expression.Call(contextArg, finalMethod, callBody);

                var body         = Expression.Block(new[] { requestArg }, assignRequest, callBody);
                var compiledBody = Expression.Lambda(body, contextArg).Compile();

                this.MethodBody = BuildMethodBodyWithFilter((Func <StreamingHubContext, ValueTask>)compiledBody);
            }
            catch (Exception ex)
            {
                throw new InvalidOperationException($"Can't create handler. Path:{ToString()}", ex);
            }
        }
コード例 #9
0
ファイル: PingClient.cs プロジェクト: lizhi5753186/MagicOnion
 static PingClient()
 {
     Method             = new Method <byte[], byte[]>(MethodType.DuplexStreaming, "IMagicOnionEmbeddedPing", "Ping", MagicOnionMarshallers.ByteArrayMarshaller, MagicOnionMarshallers.ByteArrayMarshaller);
     RequestMarshaller  = MagicOnionMarshallers.CreateZeroFormatterMarshaller(ZeroFormatter.Formatters.Formatter <ZeroFormatter.Formatters.DefaultResolver, DateTime> .Default);
     ResponseMarshaller = MagicOnionMarshallers.CreateZeroFormatterMarshaller(Formatter <ZeroFormatter.Formatters.DefaultResolver, double> .Default);
 }
コード例 #10
0
        public async Task Invoke(HttpContext httpContext)
        {
            try
            {
                var path = httpContext.Request.Path.Value;

                MethodHandler handler;
                if (!handlers.TryGetValue(path, out handler))
                {
                    await next(httpContext);

                    return;
                }

                // from form...
                object deserializedObject;
                if (httpContext.Request.ContentType == "application/x-www-form-urlencoded")
                {
                    //object parameters
                    var args     = new List <object>();
                    var typeArgs = new List <Type>();
                    foreach (var p in handler.MethodInfo.GetParameters())
                    {
                        typeArgs.Add(p.ParameterType);

                        StringValues stringValues;
                        if (httpContext.Request.Form.TryGetValue(p.Name, out stringValues))
                        {
                            if (p.ParameterType == typeof(string))
                            {
                                args.Add((string)stringValues);
                            }
                            else if (p.ParameterType.GetTypeInfo().IsEnum)
                            {
                                args.Add(Enum.Parse(p.ParameterType, (string)stringValues));
                            }
                            else
                            {
                                var collectionType = GetCollectionType(p.ParameterType);
                                if (stringValues.Count == 1 || collectionType == null)
                                {
                                    var values = (string)stringValues;
                                    if (p.ParameterType == typeof(DateTime) || p.ParameterType == typeof(DateTimeOffset) || p.ParameterType == typeof(DateTime?) || p.ParameterType == typeof(DateTimeOffset?))
                                    {
                                        values = "\"" + values + "\"";
                                    }

                                    args.Add(JsonConvert.DeserializeObject(values, p.ParameterType));
                                }
                                else
                                {
                                    string serializeTarget;
                                    if (collectionType == typeof(string))
                                    {
                                        serializeTarget = "[" + string.Join(", ", stringValues.Select(x => JsonConvert.SerializeObject(x))) + "]"; // escape serialzie
                                    }
                                    else if (collectionType.GetTypeInfo().IsEnum || collectionType == typeof(DateTime) || collectionType == typeof(DateTimeOffset) || collectionType == typeof(DateTime?) || collectionType == typeof(DateTimeOffset?))
                                    {
                                        serializeTarget = "[" + string.Join(", ", stringValues.Select(x => "\"" + x + "\"")) + "]";
                                    }
                                    else
                                    {
                                        serializeTarget = "[" + (string)stringValues + "]";
                                    }

                                    args.Add(JsonConvert.DeserializeObject(serializeTarget, p.ParameterType));
                                }
                            }
                        }
                        else
                        {
                            if (p.HasDefaultValue)
                            {
                                args.Add(p.DefaultValue);
                            }
                            else
                            {
                                args.Add(null);
                            }
                        }
                    }

                    deserializedObject = MagicOnionMarshallers.InsantiateDynamicArgumentTuple(typeArgs.ToArray(), args.ToArray());
                }
                else
                {
                    string body;
                    using (var sr = new StreamReader(httpContext.Request.Body, Encoding.UTF8))
                    {
                        body = sr.ReadToEnd();
                    }

                    if (handler.RequestType == typeof(byte[]) && string.IsNullOrWhiteSpace(body))
                    {
                        body = "[]";
                    }
                    deserializedObject = Newtonsoft.Json.JsonConvert.DeserializeObject(body, handler.RequestType);
                }

                // JSON to C# Object to MessagePack
                var requestObject = handler.BoxedSerialize(deserializedObject);

                var method = new Method <byte[], byte[]>(MethodType.Unary, handler.ServiceName, handler.MethodInfo.Name, MagicOnionMarshallers.ThroughMarshaller, MagicOnionMarshallers.ThroughMarshaller);

                // create header
                var metadata = new Metadata();
                foreach (var header in httpContext.Request.Headers)
                {
                    metadata.Add(header.Key, header.Value);
                }

                var invoker     = new DefaultCallInvoker(channel);
                var rawResponse = await invoker.AsyncUnaryCall(method, null, default(CallOptions).WithHeaders(metadata), requestObject);

                // MessagePack -> Object -> Json
                var obj = handler.BoxedDeserialize(rawResponse);
                var v   = JsonConvert.SerializeObject(obj, new[] { new Newtonsoft.Json.Converters.StringEnumConverter() });
                httpContext.Response.ContentType = "application/json";
                await httpContext.Response.WriteAsync(v);
            }
            catch (Exception ex)
            {
                httpContext.Response.StatusCode = 500;
                await httpContext.Response.WriteAsync(ex.ToString());
            }
        }
コード例 #11
0
ファイル: MethodHandler.cs プロジェクト: h-shn-k/MagicOnion
        public MethodHandler(MagicOnionOptions options, Type classType, MethodInfo methodInfo)
        {
            this.ServiceType = classType;
            this.ServiceName = classType.GetInterfaces().First(x => x.IsGenericType && x.GetGenericTypeDefinition() == typeof(IService <>)).GetGenericArguments()[0].Name;
            this.MethodInfo  = methodInfo;
            MethodType mt;

            this.UnwrappedResponseType = UnwrapResponseType(methodInfo, out mt, out responseIsTask, out this.RequestType);
            this.MethodType            = mt;
            this.resolver = options.FormatterResolver;

            var parameters = methodInfo.GetParameters();

            if (RequestType == null)
            {
                this.RequestType = MagicOnionMarshallers.CreateRequestTypeAndSetResolver(classType.Name + "/" + methodInfo.Name, parameters, ref resolver);
            }

            this.AttributeLookup = classType.GetCustomAttributes(true)
                                   .Concat(methodInfo.GetCustomAttributes(true))
                                   .Cast <Attribute>()
                                   .ToLookup(x => x.GetType());

            this.filters = options.GlobalFilters
                           .Concat(classType.GetCustomAttributes <MagicOnionFilterAttribute>(true))
                           .Concat(methodInfo.GetCustomAttributes <MagicOnionFilterAttribute>(true))
                           .OrderBy(x => x.Order)
                           .ToArray();

            // options
            this.isReturnExceptionStackTraceInErrorDetail = options.IsReturnExceptionStackTraceInErrorDetail;
            this.logger = options.MagicOnionLogger;

            // prepare lambda parameters
            var contextArg  = Expression.Parameter(typeof(ServiceContext), "context");
            var contextBind = Expression.Bind(classType.GetProperty("Context"), contextArg);
            var instance    = Expression.MemberInit(Expression.New(classType), contextBind);

            switch (MethodType)
            {
            case MethodType.Unary:
            case MethodType.ServerStreaming:
                // (ServiceContext context) =>
                // {
                //      var request = LZ4MessagePackSerializer.Deserialize<T>(context.Request, context.Resolver);
                //      var result = new FooService() { Context = context }.Bar(request.Item1, request.Item2);
                //      return MethodHandlerResultHelper.SerializeUnaryResult(result, context);
                // };
                try
                {
                    var flags       = BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic;
                    var staticFlags = BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic;

                    var requestArg  = Expression.Parameter(RequestType, "request");
                    var getResolver = Expression.Property(contextArg, typeof(ServiceContext).GetProperty("FormatterResolver", flags));

                    var contextRequest = Expression.Property(contextArg, typeof(ServiceContext).GetProperty("Request", flags));

                    var callDeserialize = Expression.Call(messagePackDeserialize.MakeGenericMethod(RequestType), contextRequest, getResolver);
                    var assignRequest   = Expression.Assign(requestArg, callDeserialize);

                    Expression[] arguments = new Expression[parameters.Length];
                    if (parameters.Length == 1)
                    {
                        arguments[0] = requestArg;
                    }
                    else
                    {
                        for (int i = 0; i < parameters.Length; i++)
                        {
                            arguments[i] = Expression.Field(requestArg, "Item" + (i + 1));
                        }
                    }

                    var callBody = Expression.Call(instance, methodInfo, arguments);

                    if (MethodType == MethodType.Unary)
                    {
                        var finalMethod = (responseIsTask)
                                ? typeof(MethodHandlerResultHelper).GetMethod("SerializeTaskUnaryResult", staticFlags).MakeGenericMethod(UnwrappedResponseType)
                                : typeof(MethodHandlerResultHelper).GetMethod("SerializeUnaryResult", staticFlags).MakeGenericMethod(UnwrappedResponseType);
                        callBody = Expression.Call(finalMethod, callBody, contextArg);
                    }
                    else
                    {
                        if (!responseIsTask)
                        {
                            callBody = Expression.Call(typeof(Task).GetMethod("FromResult").MakeGenericMethod(MethodInfo.ReturnType), callBody);
                        }
                    }

                    var body         = Expression.Block(new[] { requestArg }, assignRequest, callBody);
                    var compiledBody = Expression.Lambda(body, contextArg).Compile();

                    this.methodBody = BuildMethodBodyWithFilter((Func <ServiceContext, Task>)compiledBody);
                }
                catch (Exception ex)
                {
                    throw new InvalidOperationException($"Can't create handler. Path:{ToString()}", ex);
                }
                break;

            case MethodType.ClientStreaming:
            case MethodType.DuplexStreaming:
                if (parameters.Length != 0)
                {
                    throw new InvalidOperationException($"{MethodType} does not support method parameters. If you need to send initial parameter, use header instead. Path:{ToString()}");
                }

                // (ServiceContext context) => new FooService() { Context = context }.Bar();
                try
                {
                    var body = Expression.Call(instance, methodInfo);

                    if (MethodType == MethodType.ClientStreaming)
                    {
                        var staticFlags = BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic;
                        var finalMethod = (responseIsTask)
                                ? typeof(MethodHandlerResultHelper).GetMethod("SerializeTaskClientStreamingResult", staticFlags).MakeGenericMethod(RequestType, UnwrappedResponseType)
                                : typeof(MethodHandlerResultHelper).GetMethod("SerializeClientStreamingResult", staticFlags).MakeGenericMethod(RequestType, UnwrappedResponseType);
                        body = Expression.Call(finalMethod, body, contextArg);
                    }
                    else
                    {
                        if (!responseIsTask)
                        {
                            body = Expression.Call(typeof(Task).GetMethod("FromResult").MakeGenericMethod(MethodInfo.ReturnType), body);
                        }
                    }

                    var compiledBody = Expression.Lambda(body, contextArg).Compile();

                    this.methodBody = BuildMethodBodyWithFilter((Func <ServiceContext, Task>)compiledBody);
                }
                catch (Exception ex)
                {
                    throw new InvalidOperationException($"Can't create handler. Path:{ToString()}", ex);
                }
                break;

            default:
                throw new InvalidOperationException("Unknown MethodType:" + MethodType + $"Path:{ToString()}");
            }
        }
コード例 #12
0
 static HeartbeatClient()
 {
     DuplexStreamingAsyncMethod             = new Method <byte[], byte[]>(MethodType.DuplexStreaming, "IMagicOnionEmbeddedHeartbeat", "Connect", MagicOnionMarshallers.ByteArrayMarshaller, MagicOnionMarshallers.ByteArrayMarshaller);
     DuplexStreamingAsyncRequestMarshaller  = MagicOnionMarshallers.CreateZeroFormatterMarshaller(ZeroFormatter.Formatters.Formatter <ZeroFormatter.Formatters.DefaultResolver, bool> .Default);
     DuplexStreamingAsyncResponseMarshaller = MagicOnionMarshallers.CreateZeroFormatterMarshaller(Formatter <ZeroFormatter.Formatters.DefaultResolver, bool> .Default);
 }
コード例 #13
0
        public MethodHandler(MagicOnionOptions options, Type classType, MethodInfo methodInfo)
        {
            this.ServiceType = classType;
            this.ServiceName = classType.GetInterfaces().First(x => x.IsGenericType && x.GetGenericTypeDefinition() == typeof(IService <>)).GetGenericArguments()[0].Name;
            this.MethodInfo  = methodInfo;
            MethodType mt;

            this.UnwrappedResponseType = UnwrapResponseType(methodInfo, out mt, out responseIsTask, out this.RequestType);
            this.MethodType            = mt;

            var parameters = methodInfo.GetParameters();

            if (RequestType == null)
            {
                this.RequestType = MagicOnionMarshallers.CreateRequestTypeAndMarshaller(options.ZeroFormatterTypeResolverType, classType.Name + "/" + methodInfo.Name, parameters, out requestMarshaller);
            }
            else
            {
                this.requestMarshaller = MagicOnionMarshallers.CreateZeroFormattertMarshallerReflection(options.ZeroFormatterTypeResolverType, RequestType);
            }

            this.responseMarshaller = MagicOnionMarshallers.CreateZeroFormattertMarshallerReflection(options.ZeroFormatterTypeResolverType, UnwrappedResponseType);

            this.AttributeLookup = classType.GetCustomAttributes(true)
                                   .Concat(methodInfo.GetCustomAttributes(true))
                                   .Cast <Attribute>()
                                   .ToLookup(x => x.GetType());

            this.filters = options.GlobalFilters
                           .Concat(classType.GetCustomAttributes <MagicOnionFilterAttribute>(true))
                           .Concat(methodInfo.GetCustomAttributes <MagicOnionFilterAttribute>(true))
                           .OrderBy(x => x.Order)
                           .ToArray();

            // options
            this.isReturnExceptionStackTraceInErrorDetail = options.IsReturnExceptionStackTraceInErrorDetail;
            this.logger = options.MagicOnionLogger;

            // prepare lambda parameters
            var contextArg  = Expression.Parameter(typeof(ServiceContext), "context");
            var contextBind = Expression.Bind(classType.GetProperty("Context"), contextArg);
            var instance    = Expression.MemberInit(Expression.New(classType), contextBind);

            switch (MethodType)
            {
            case MethodType.Unary:
            case MethodType.ServerStreaming:
                // (ServiceContext context) =>
                // {
                //      var request = ((Marshaller<TRequest>)context.RequestMarshaller).Deserializer.Invoke(context.Request);
                //      return new FooService() { Context = context }.Bar(request.Item1, request.Item2);
                // };
            {
                var flags          = BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic;
                var marshallerType = typeof(Marshaller <>).MakeGenericType(RequestType);

                var requestArg = Expression.Parameter(RequestType, "request");

                var requestMarshalleExpr = Expression.Convert(Expression.Property(contextArg, typeof(ServiceContext).GetProperty("RequestMarshaller", flags)), marshallerType);
                var deserializer         = Expression.Property(requestMarshalleExpr, "Deserializer");
                var callDeserialize      = Expression.Call(deserializer, typeof(Func <,>).MakeGenericType(typeof(byte[]), RequestType).GetMethod("Invoke"), Expression.Property(contextArg, typeof(ServiceContext).GetProperty("Request", flags)));

                var assignRequest = Expression.Assign(requestArg, callDeserialize);

                Expression[] arguments = new Expression[parameters.Length];
                if (parameters.Length == 1)
                {
                    arguments[0] = requestArg;
                }
                else
                {
                    for (int i = 0; i < parameters.Length; i++)
                    {
                        arguments[i] = Expression.Field(requestArg, "Item" + (i + 1));
                    }
                }

                var callBody = Expression.Call(instance, methodInfo, arguments);
                if (!responseIsTask)
                {
                    callBody = Expression.Call(typeof(Task).GetMethod("FromResult").MakeGenericMethod(MethodInfo.ReturnType), callBody);
                }

                var body         = Expression.Block(new[] { requestArg }, assignRequest, callBody);
                var compiledBody = Expression.Lambda(body, contextArg).Compile();

                this.methodBody = BuildMethodBodyWithFilter((Func <ServiceContext, Task>)compiledBody);
            }
            break;

            case MethodType.ClientStreaming:
            case MethodType.DuplexStreaming:
                if (parameters.Length != 0)
                {
                    throw new InvalidOperationException($"{MethodType} does not support method parameters. If you need to send initial parameter, use header instead.");
                }

                // (ServiceContext context) => new FooService() { Context = context }.Bar();
                {
                    var body = Expression.Call(instance, methodInfo);
                    if (!responseIsTask)
                    {
                        body = Expression.Call(typeof(Task).GetMethod("FromResult").MakeGenericMethod(MethodInfo.ReturnType), body);
                    }

                    var compiledBody = Expression.Lambda(body, contextArg).Compile();

                    this.methodBody = BuildMethodBodyWithFilter((Func <ServiceContext, Task>)compiledBody);
                }
                break;

            default:
                throw new InvalidOperationException("Unknown MethodType:" + MethodType);
            }

            // Utility
            {
                // (object requestMarshaller, object value) => ((Marshaller<TRequest>)requestMarshaller).Serializer.Invoke((TRequest)value);
                var marshallerType       = typeof(Marshaller <>).MakeGenericType(RequestType);
                var requestMarshallerArg = Expression.Parameter(typeof(object), "requestMarshaller");
                var valueArg             = Expression.Parameter(typeof(object), "value");
                var serializer           = Expression.Property(Expression.Convert(requestMarshallerArg, marshallerType), "Serializer");
                var callSerialize        = Expression.Call(serializer, typeof(Func <,>).MakeGenericType(RequestType, typeof(byte[])).GetMethod("Invoke"),
                                                           Expression.Convert(valueArg, RequestType));

                boxedRequestSerialize = Expression.Lambda <Func <object, object, byte[]> >(callSerialize, requestMarshallerArg, valueArg).Compile();
            }
            {
                // (object responseMarshaller, byte[] value) => ((Marshaller<TResponse>)requestMarshaller).Deserializer.Invoke(value);
                var marshallerType        = typeof(Marshaller <>).MakeGenericType(UnwrappedResponseType);
                var responseMarshallerArg = Expression.Parameter(typeof(object), "responseMarshaller");
                var valueArg        = Expression.Parameter(typeof(byte[]), "value");
                var deserializer    = Expression.Property(Expression.Convert(responseMarshallerArg, marshallerType), "Deserializer");
                var callDeserialize = Expression.Convert(Expression.Call(deserializer, typeof(Func <,>).MakeGenericType(typeof(byte[]), UnwrappedResponseType).GetMethod("Invoke"), valueArg), typeof(object));
                boxedResponseDeserialize = Expression.Lambda <Func <object, byte[], object> >(callDeserialize, responseMarshallerArg, valueArg).Compile();
            }
        }
コード例 #14
0
 static ISendMetadataClient()
 {
     PangPongMethod             = new Method <byte[], byte[]>(MethodType.Unary, "ISendMetadata", "PangPong", MagicOnionMarshallers.ByteArrayMarshaller, MagicOnionMarshallers.ByteArrayMarshaller);
     PangPongRequestMarshaller  = MagicOnionMarshallers.CreateZeroFormatterMarshaller(ZeroFormatter.Formatters.Formatter <ZeroFormatter.Formatters.DefaultResolver, byte[]> .Default);
     PangPongResponseMarshaller = MagicOnionMarshallers.CreateZeroFormatterMarshaller(Formatter <ZeroFormatter.Formatters.DefaultResolver, int> .Default);
 }