コード例 #1
0
        private async Task ExecuteRpcAction(ApiCallContext <RequestContext <IScenePeer> > ctx, Func <T, RequestContext <IScenePeer>, IDependencyResolver, Task> action)
        {
            using (var scope = _scene.DependencyResolver.CreateChild(Constants.ApiRequestTag, ctx.Builder))
            {
                var controller = scope.Resolve <T>();
                try
                {
                    if (controller == null)
                    {
                        throw new InvalidOperationException("The controller could not be found. Make sure it has been properly registered in the dependency manager.");
                    }
                    //controller.Request = ctx;
                    controller.CancellationToken = ctx.Context.CancellationToken;
                    controller.Peer = ctx.Context.RemotePeer;

                    await action(controller, ctx.Context, scope);
                }
                catch (ClientException)
                {
                    throw;
                }
                catch (Exception ex)
                {
                    scope.Resolve <ILogger>().Log(LogLevel.Error, ctx.Route, $"An exception occurred while executing action '{ctx.Route}' in controller '{typeof(T).Name}'.", ex);
                    throw;
                }
            }
        }
コード例 #2
0
        private async Task ExecuteRouteAction(ApiCallContext <Packet <IScenePeerClient> > ctx, Func <T, Packet <IScenePeerClient>, IDependencyResolver, Task> action)
        {
            using (var scope = _scene.DependencyResolver.CreateChild(Constants.ApiRequestTag, ctx.Builder))
            {
                var controller = scope.Resolve <T>();
                controller.Peer = ctx.Context.Connection;

                try
                {
                    if (controller == null)
                    {
                        throw new InvalidOperationException("The controller could not be found. Make sure it has been properly registered in the dependency manager.");
                    }
                    await action(controller, ctx.Context, scope);
                }
                catch (Exception ex)
                {
                    if (controller == null || !await controller.HandleException(new ApiExceptionContext(ctx.Route, ex, ctx.Context)))
                    {
                        scope.Resolve <ILogger>().Log(LogLevel.Error, ctx.Route, $"An exception occurred while executing action '{ctx.Route}' in controller '{typeof(T).Name}'.", ex);
                        throw;
                    }
                }
            }
        }
コード例 #3
0
        private bool TryAddRoute(Type controllerType, MethodInfo method)
        {
            var attr = method.GetCustomAttribute <ApiAttribute>();

            if (attr == null)
            {
                return(false);
            }
            var route      = attr.Route ?? GetProcedureName(controllerType, method, false);
            var returnType = method.ReturnType;

            if (attr.Type == ApiType.FireForget && returnType != typeof(Task) && returnType != typeof(void))
            {
                return(false);
            }



            if (attr.Access == ApiAccess.Public)
            {
                if (attr.Type == ApiType.FireForget)
                {
                    var a = CreateExecuteActionFunction <Packet <IScenePeerClient> >(method);
                    _scene.AddRoute(route, packet =>
                    {
                        var initialApiCallCtx = new ApiCallContext <Packet <IScenePeerClient> >(packet, method, route);
                        Func <ApiCallContext <Packet <IScenePeerClient> >, Task> next = apiCallContext => ExecuteRouteAction(initialApiCallCtx, (c, pctx, r) => a(c, pctx, r));
                        foreach (var handler in _scene.DependencyResolver.Resolve <Func <IEnumerable <IApiHandler> > >()())
                        {
                            next = WrapWithHandler(handler.RunFF, next);
                        }
                        return(next(initialApiCallCtx));
                    }, _ => _);
                }
                else
                {
                    var a = CreateExecuteActionFunction <RequestContext <IScenePeerClient> >(method);
                    _scene.AddProcedure(route, packet =>
                    {
                        var initialApiCallCtx = new ApiCallContext <RequestContext <IScenePeerClient> >(packet, method, route);
                        Func <ApiCallContext <RequestContext <IScenePeerClient> >, Task> next = apiCallContext => ExecuteRpcAction(initialApiCallCtx, (c, pctx, r) => a(c, pctx, r));
                        foreach (var handler in _scene.DependencyResolver.Resolve <Func <IEnumerable <IApiHandler> > >()())
                        {
                            next = WrapWithHandler(handler.RunRpc, next);
                        }
                        return(next(initialApiCallCtx));
                    }, true);
                }
            }
            else //S2S
            {
                if (attr.Type == ApiType.FireForget)
                {
                    var a = CreateExecuteActionFunction <Packet <IScenePeer> >(method);
                    _scene.AddInternalRoute(route, packet =>
                    {
                        var initialApiCallCtx = new ApiCallContext <Packet <IScenePeer> >(packet, method, route);
                        Func <ApiCallContext <Packet <IScenePeer> >, Task> next = apiCallContext => ExecuteRouteAction(initialApiCallCtx, (c, pctx, r) => a(c, pctx, r));
                        foreach (var handler in _scene.DependencyResolver.Resolve <Func <IEnumerable <IApiHandler> > >()())
                        {
                            next = WrapWithHandler(handler.RunFF, next);
                        }
                        return(next(initialApiCallCtx));
                    }, _ => _);
                }
                else
                {
                    var a = CreateExecuteActionFunction <RequestContext <IScenePeer> >(method);
                    _scene.Starting.Add(d =>
                    {
                        _scene.DependencyResolver.Resolve <RpcService>().AddInternalProcedure(route, packet =>
                        {
                            var initialApiCallCtx = new ApiCallContext <RequestContext <IScenePeer> >(packet, method, route);
                            Func <ApiCallContext <RequestContext <IScenePeer> >, Task> next = apiCallContext => ExecuteRpcAction(initialApiCallCtx, (c, pctx, r) => a(c, pctx, r));
                            foreach (var handler in _scene.DependencyResolver.Resolve <Func <IEnumerable <IApiHandler> > >()())
                            {
                                next = WrapWithHandler(handler.RunRpc, next);
                            }

                            return(next(initialApiCallCtx));
                        }, true);
                        return(Task.CompletedTask);
                    });
                }
            }
            return(true);
        }
コード例 #4
0
        public void RegisterControllers()
        {
            var type = typeof(T);

            _scene.Connecting.Add(p => ExecuteConnecting(p));
            _scene.ConnectionRejected.Add(p => ExecuteConnectionRejected(p));
            _scene.Connected.Add(p => ExecuteConnected(p));
            _scene.Disconnected.Add(args => ExecuteDisconnected(args));
            foreach (var method in type.GetMethods())
            {
                var procedureName = GetProcedureName(type, method);
                if (IsRawRpc <IScenePeerClient>(method))
                {
                    var ctxParam        = Expression.Parameter(typeof(RequestContext <IScenePeerClient>), "ctx");
                    var controllerParam = Expression.Parameter(typeof(T), "controller");
                    var callExpr        = Expression.Call(controllerParam, method, ctxParam);



                    var action = Expression.Lambda <Func <T, RequestContext <IScenePeerClient>, Task> >(callExpr, controllerParam, ctxParam).Compile();


                    _scene.AddProcedure(procedureName, ctx =>
                    {
                        var initialApiCallCtx = new ApiCallContext <RequestContext <IScenePeerClient> >(ctx, method, procedureName);

                        Func <ApiCallContext <RequestContext <IScenePeerClient> >, Task> next = apiCallContext => ExecuteRpcAction(initialApiCallCtx, (c, pctx, r) => action(c, pctx));
                        foreach (var handler in _scene.DependencyResolver.Resolve <Func <IEnumerable <IApiHandler> > >()())
                        {
                            next = WrapWithHandler(handler.RunRpc, next);
                        }
                        return(next(initialApiCallCtx));
                    });
                }
                else if (IsRawRoute <IScenePeerClient>(method))
                {
                    var ctxParam        = Expression.Parameter(typeof(Packet <IScenePeerClient>), "ctx");
                    var controllerParam = Expression.Parameter(typeof(T), "controller");
                    var callExpr        = Expression.Call(controllerParam, method, ctxParam);

                    var action = Expression.Lambda <Func <T, Packet <IScenePeerClient>, Task> >(callExpr, controllerParam, ctxParam).Compile();
                    _scene.AddRoute(procedureName, packet =>
                    {
                        var initialApiCallCtx = new ApiCallContext <Packet <IScenePeerClient> >(packet, method, procedureName);
                        Func <ApiCallContext <Packet <IScenePeerClient> >, Task> next = apiCallContext => ExecuteRouteAction(initialApiCallCtx, (c, pctx, r) => action(c, pctx));
                        foreach (var handler in _scene.DependencyResolver.Resolve <Func <IEnumerable <IApiHandler> > >()())
                        {
                            next = WrapWithHandler(handler.RunFF, next);
                        }
                        return(next(initialApiCallCtx));
                    }, _ => _);
                }
                else if (IsRawRpc <IScenePeer>(method))
                {
                    var ctxParam        = Expression.Parameter(typeof(RequestContext <IScenePeer>), "ctx");
                    var controllerParam = Expression.Parameter(typeof(T), "controller");
                    var callExpr        = Expression.Call(controllerParam, method, ctxParam);

                    var action = Expression.Lambda <Func <T, RequestContext <IScenePeer>, Task> >(callExpr, controllerParam, ctxParam).Compile();
                    _scene.Starting.Add(async parameters =>
                    {
                        _scene.DependencyResolver.Resolve <RpcService>().AddInternalProcedure(procedureName, ctx =>
                        {
                            var initialApiCallCtx = new ApiCallContext <RequestContext <IScenePeer> >(ctx, method, procedureName);
                            Func <ApiCallContext <RequestContext <IScenePeer> >, Task> next = apiCallContext => ExecuteRpcAction(initialApiCallCtx, (c, pctx, r) => action(c, pctx));
                            foreach (var handler in _scene.DependencyResolver.Resolve <Func <IEnumerable <IApiHandler> > >()())
                            {
                                next = WrapWithHandler(handler.RunRpc, next);
                            }

                            return(next(initialApiCallCtx));
                        }, false);
                        await Task.FromResult(true);
                    });
                }
                else if (IsRawRoute <IScenePeer>(method))
                {
                    var ctxParam        = Expression.Parameter(typeof(Packet <IScenePeer>), "ctx");
                    var controllerParam = Expression.Parameter(typeof(T), "controller");
                    var callExpr        = Expression.Call(controllerParam, method, ctxParam);

                    var action = Expression.Lambda <Func <T, Packet <IScenePeer>, Task> >(callExpr, controllerParam, ctxParam).Compile();
                    _scene.AddInternalRoute(procedureName, packet =>
                    {
                        var initialApiCallCtx = new ApiCallContext <Packet <IScenePeer> >(packet, method, procedureName);
                        Func <ApiCallContext <Packet <IScenePeer> >, Task> next = apiCallContext => ExecuteRouteAction(initialApiCallCtx, (c, pctx, r) => action(c, pctx));
                        foreach (var handler in _scene.DependencyResolver.Resolve <Func <IEnumerable <IApiHandler> > >()())
                        {
                            next = WrapWithHandler(handler.RunFF, next);
                        }
                        return(next(initialApiCallCtx));
                    }, _ => _);
                }
                else
                {
                    TryAddRoute(type, method);
                }
            }
        }