예제 #1
0
        private void DiscoverHubMethods()
        {
            var hubType     = typeof(THub);
            var hubTypeInfo = hubType.GetTypeInfo();
            var hubName     = hubType.Name;

            foreach (var methodInfo in HubReflectionHelper.GetHubMethods(hubType))
            {
                var methodName =
                    methodInfo.GetCustomAttribute <HubMethodNameAttribute>()?.Name ??
                    methodInfo.Name;

                if (_methods.ContainsKey(methodName))
                {
                    throw new NotSupportedException($"Duplicate definitions of '{methodName}'. Overloading is not supported.");
                }

                var executor            = ObjectMethodExecutor.Create(methodInfo, hubTypeInfo);
                var authorizeAttributes = methodInfo.GetCustomAttributes <AuthorizeAttribute>(inherit: true);
                _methods[methodName] = new HubMethodDescriptor(executor, authorizeAttributes);

                _logger.HubMethodBound(hubName, methodName);
            }
        }
예제 #2
0
        public async Task <Response <OrleansResponseMessage> > Invoke(GrainReference grain, GrainRouteValues route)
        {
            ObjectMethodExecutor executor;

            object[] parameters;
            try
            {
                string key = $"{route.SiloName}.{route.GrainName}.{route.GrainMethodName}";
                executor = _cachedExecutors.GetOrAdd(key, (_key) =>
                {
                    ObjectMethodExecutor _executor = ObjectMethodExecutor.Create(route.GrainMethod, grain.GrainType.GetTypeInfo());
                    return(_executor);
                });
                parameters = GetParameters(executor, route);
            }
            catch (Exception ex)
            {
                _logger.LogError($"Binding parameter failed", ex);
                return(new ErrorResponse <OrleansResponseMessage>(new UnknownError(ex.Message)));
            }
            try
            {
                return(await this.Invoke(executor, grain, parameters));
            }
            catch (Exception ex)
            {
                _logger.LogError($"Request {grain.GrainType.Name} Orleans failed,", ex);
                if (ex.InnerException != null && ex.InnerException is Orleans.Runtime.OrleansMessageRejectionException)
                {
                    await Task.Delay(1);

                    return(await this.Invoke(executor, grain, parameters));
                }
                throw ex;
            }
        }
예제 #3
0
 private static ObjectMethodExecutor CreateExecutor(ControllerActionDescriptor actionDescriptor)
 {
     return(ObjectMethodExecutor.Create(actionDescriptor.MethodInfo, actionDescriptor.ControllerTypeInfo));
 }
예제 #4
0
        private ObjectMethodExecutor GetExecutorForMethod(string methodName, object[] parameterDefaultValues)
        {
            var method = typeof(TestObject).GetMethod(methodName);

            return(ObjectMethodExecutor.Create(method, targetTypeInfo, parameterDefaultValues));
        }
예제 #5
0
        private ObjectMethodExecutor GetExecutorForMethod(string methodName)
        {
            var method = typeof(TestObject).GetMethod(methodName);

            return(ObjectMethodExecutor.Create(method, targetTypeInfo));
        }
예제 #6
0
 /// <summary>
 /// Initializes a new instance of the <see cref="OperationResolver"/> class.
 /// </summary>
 /// <param name="operation">The <see cref="GraphOperationDescriptor"/> describing the current GraphQL operation.</param>
 /// <param name="binderProvider">The <see cref="IArgumentBinderProvider"/> to provide <see cref="IArgumentBinder"/>.</param>
 public OperationResolver(GraphOperationDescriptor operation, IArgumentBinderProvider binderProvider)
 {
     _operation = operation ?? throw new ArgumentNullException(nameof(operation));
     _executor  = ObjectMethodExecutor.Create(_operation.MethodInfo, _operation.Service.ServiceType.GetTypeInfo());
     _binder    = Guard.ArgumentNotNull(binderProvider, nameof(binderProvider)).GetArgumentBinder();
 }
예제 #7
0
 public object Compile() =>
 ObjectMethodExecutor.Create(_t.GetMethod(nameof(Foo)), _t.GetTypeInfo());
예제 #8
0
        public static IApplicationBuilder UseCapDashboard(this IApplicationBuilder app)
        {
            if (app == null)
            {
                throw new ArgumentNullException(nameof(app));
            }

            var provider = app.ApplicationServices;

            var options = provider.GetService <DashboardOptions>();

            if (options != null)
            {
                if (provider.GetService <DiscoveryOptions>() != null)
                {
                    app.UseMiddleware <GatewayProxyMiddleware>();
                }

                app.UseMiddleware <UiMiddleware>();

                app.Map(options.PathMatch + "/api", false, x =>
                {
                    var builder = new RouteBuilder(x);

                    var methods = typeof(RouteActionProvider).GetMethods(BindingFlags.Instance | BindingFlags.Public);

                    foreach (var method in methods)
                    {
                        var executor = ObjectMethodExecutor.Create(method, typeof(RouteActionProvider).GetTypeInfo());

                        var getAttr = method.GetCustomAttribute <HttpGetAttribute>();
                        if (getAttr != null)
                        {
                            builder.MapGet(getAttr.Template, async(request, response, data) =>
                            {
                                if (!await Authentication(request.HttpContext, options))
                                {
                                    response.StatusCode = StatusCodes.Status401Unauthorized;
                                    return;
                                }

                                var actionProvider = new RouteActionProvider(request, response, data);
                                try
                                {
                                    await executor.ExecuteAsync(actionProvider, null);
                                }
                                catch (Exception ex)
                                {
                                    response.StatusCode = StatusCodes.Status500InternalServerError;
                                    await response.WriteAsync(ex.Message);
                                }
                            });
                        }

                        var postAttr = method.GetCustomAttribute <HttpPostAttribute>();
                        if (postAttr != null)
                        {
                            builder.MapPost(postAttr.Template, async(request, response, data) =>
                            {
                                if (!await Authentication(request.HttpContext, options))
                                {
                                    response.StatusCode = StatusCodes.Status401Unauthorized;
                                    return;
                                }

                                var actionProvider = new RouteActionProvider(request, response, data);
                                try
                                {
                                    await executor.ExecuteAsync(actionProvider, null);
                                }
                                catch (Exception ex)
                                {
                                    response.StatusCode = StatusCodes.Status500InternalServerError;
                                    await response.WriteAsync(ex.Message);
                                }
                            });
                        }
                    }

                    var capRouter = builder.Build();

                    x.UseRouter(capRouter);
                });
            }

            return(app);
        }
        /// <summary>
        /// 调用订阅者方法
        /// </summary>
        /// <param name="context"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        public virtual async Task <ConsumerExecutedResult> InvokeAsync(ConsumerContext context, CancellationToken cancellationToken = default)
        {
            cancellationToken.ThrowIfCancellationRequested();

            var methodInfo    = context.ConsumerDescriptor.MethodInfo;
            var reflectedType = methodInfo.ReflectedType.Name;

            _logger.LogDebug("Executing subscriber method : {0}", methodInfo.Name);

            var key      = $"{methodInfo.Module.Name}_{reflectedType}_{methodInfo.MetadataToken}";
            var executor = _executors.GetOrAdd(key, x => ObjectMethodExecutor.Create(methodInfo, context.ConsumerDescriptor.ImplTypeInfo));

            using var scope = _serviceProvider.CreateScope();

            var provider = scope.ServiceProvider;

            var obj = GetInstance(provider, context);

            var message = context.DeliverMessage;
            var parameterDescriptors = context.ConsumerDescriptor.Parameters;
            var executeParameters    = new object[parameterDescriptors.Count];
            // 租户数据可能在消息标头中
            var tenantId = message.GetTenantIdOrNull();

            for (var i = 0; i < parameterDescriptors.Count; i++)
            {
                if (parameterDescriptors[i].IsFromCap)
                {
                    executeParameters[i] = new CapHeader(message.Headers);
                }
                else
                {
                    if (message.Value != null)
                    {
                        if (_serializer.IsJsonType(message.Value))  // use ISerializer when reading from storage, skip other objects if not Json
                        {
                            var eventData = _serializer.Deserialize(message.Value, parameterDescriptors[i].ParameterType);
                            // 租户数据也可能存在事件数据中
                            if (tenantId == null && eventData is IMultiTenant tenant)
                            {
                                tenantId = tenant.TenantId;
                            }
                            executeParameters[i] = eventData;
                        }
                        else
                        {
                            var converter = TypeDescriptor.GetConverter(parameterDescriptors[i].ParameterType);
                            if (converter.CanConvertFrom(message.Value.GetType()))
                            {
                                var eventData = converter.ConvertFrom(message.Value);
                                // 租户数据也可能存在事件数据中
                                if (tenantId == null && eventData is IMultiTenant tenant)
                                {
                                    tenantId = tenant.TenantId;
                                }
                                executeParameters[i] = eventData;
                            }
                            else
                            {
                                if (parameterDescriptors[i].ParameterType.IsInstanceOfType(message.Value))
                                {
                                    // 租户数据也可能存在事件数据中
                                    if (tenantId == null && message.Value is IMultiTenant tenant)
                                    {
                                        tenantId = tenant.TenantId;
                                    }
                                    executeParameters[i] = message.Value;
                                }
                                else
                                {
                                    var eventData = Convert.ChangeType(message.Value, parameterDescriptors[i].ParameterType);
                                    // 租户数据也可能存在事件数据中
                                    if (tenantId == null && eventData is IMultiTenant tenant)
                                    {
                                        tenantId = tenant.TenantId;
                                    }
                                    executeParameters[i] = eventData;
                                }
                            }
                        }
                    }
                }
            }

            // 改变租户
            using (_currentTenant.Change(tenantId))
            {
                var resultObj = await ExecuteWithParameterAsync(executor, obj, executeParameters);

                return(new ConsumerExecutedResult(resultObj, message.GetId(), message.GetCallbackName()));
            }
        }