internal async Task RunAsync(Type type, string[] args)
        {
            logger.LogTrace("BatchEngine.Run Start");

            MethodInfo method = null;
            var        ctx    = new BatchContext(args, DateTime.UtcNow, cancellationToken, logger);

            try
            {
                await interceptor.OnBatchRunBegin(ctx);

                if (type == typeof(void))
                {
                    SetFail(ctx, "Type or method does not found on this Program. args: " + string.Join(" ", args));
                    return;
                }

                var methods = type.GetMethods(BindingFlags.Public | BindingFlags.Instance | BindingFlags.DeclaredOnly);
                if (methods.Length != 1)
                {
                    SetFail(ctx, "Method can not select. T of Run/UseBatchEngine<T> have to be contain single method. Type:" + type.FullName);
                    return;
                }
                method = methods[0];
            }
            catch (Exception ex)
            {
                SetFail(ctx, "Fail to get method. Type:" + type.FullName, ex);
                return;
            }

            await RunCore(ctx, type, method, args, 0);
        }
Exemple #2
0
        public async Task RunAsync(Type type, MethodInfo method, string[] args)
        {
            logger.LogTrace("BatchEngine.Run Start");
            var ctx = new BatchContext(args, DateTime.UtcNow, cancellationToken, logger);

            await RunCore(ctx, type, method, args, 1); // 0 is type selector
        }
        async Task RunCore(BatchContext ctx, Type type, MethodInfo methodInfo, string[] args, int argsOffset)
        {
            object instance = null;

            object[] invokeArgs = null;

            try
            {
                var argumentDictionary = ParseArgument(args, argsOffset);
                invokeArgs = GetInvokeArguments(methodInfo.GetParameters(), argumentDictionary);
            }
            catch (Exception ex)
            {
                SetFail(ctx, "Fail to match method parameter on " + type.Name + "." + methodInfo.Name + ". args: " + string.Join(" ", args), ex);
                return;
            }

            try
            {
                instance = provider.GetService(type);
                typeof(BatchBase).GetProperty(nameof(BatchBase.Context)).SetValue(instance, ctx);
            }
            catch (Exception ex)
            {
                SetFail(ctx, "Fail to create BatchBase instance. Type:" + type.FullName, ex);
                return;
            }

            try
            {
                var result = methodInfo.Invoke(instance, invokeArgs);
                if (result is Task t)
                {
                    await t;
                }
            }
            catch (Exception ex)
            {
                if (ex is OperationCanceledException || ex is TaskCanceledException)
                {
                    return; // do nothing
                }

                SetFail(ctx, "Fail in batch running on " + type.Name + "." + methodInfo.Name, ex);
                return;
            }

            await interceptor.OnBatchRunComplete(ctx, null, null);

            logger.LogTrace("BatchEngine.Run Complete Successfully");
        }
        public async ValueTask OnBatchRunCompleteAsync(BatchContext context, string?errorMessageIfFailed, Exception?exceptionIfExists)
        {
            var exceptions = new AggregateExceptionHolder();

            foreach (var item in interceptors)
            {
                try
                {
                    await item.OnBatchRunCompleteAsync(context, errorMessageIfFailed, exceptionIfExists);
                }
                catch (Exception e)
                {
                    exceptions.Add(e);
                }
            }
            exceptions.ThrowIfExists();
        }
        public async ValueTask OnBatchRunBeginAsync(BatchContext context)
        {
            var exceptions = new AggregateExceptionHolder();

            foreach (var item in interceptors)
            {
                try
                {
                    await item.OnBatchRunBeginAsync(context);
                }
                catch (Exception e)
                {
                    exceptions.Add(e);
                }
            }
            exceptions.ThrowIfExists();
        }
 public ValueTask OnBatchRunCompleteAsync(BatchContext context, string errorMessageIfFailed, Exception exceptionIfExists)
 {
     return(Empty);
 }
 public ValueTask OnBatchRunBeginAsync(BatchContext context)
 {
     return(Empty);
 }
Exemple #8
0
        public async Task RunAsync(Type type, string[] args)
        {
            logger.LogTrace("BatchEngine.Run Start");

            int        argsOffset = 0;
            MethodInfo method     = null;
            var        ctx        = new BatchContext(args, DateTime.UtcNow, cancellationToken, logger);

            try
            {
                await interceptor.OnBatchRunBeginAsync(ctx);

                if (type == typeof(void))
                {
                    await SetFailAsync(ctx, "Type or method does not found on this Program. args: " + string.Join(" ", args));

                    return;
                }

                var methods = type.GetMethods(BindingFlags.Public | BindingFlags.Instance | BindingFlags.DeclaredOnly);
                if (methods.Length == 0)
                {
                    await SetFailAsync(ctx, "Method can not select. T of Run/UseBatchEngine<T> have to be contain single method or command. Type:" + type.FullName);

                    return;
                }

                MethodInfo helpMethod = null;
                foreach (var item in methods)
                {
                    var command = item.GetCustomAttribute <CommandAttribute>();
                    if (command != null)
                    {
                        if (args.Length > 0 && command.EqualsAny(args[0]))
                        {
                            // command's priority is first
                            method     = item;
                            argsOffset = 1;
                            goto RUN;
                        }
                        else
                        {
                            if (command.EqualsAny("help"))
                            {
                                helpMethod = item;
                            }
                        }
                    }
                    else
                    {
                        if (method != null)
                        {
                            await SetFailAsync(ctx, "Found two public methods(wihtout command). Type:" + type.FullName + " Method:" + method.Name + " and " + item.Name);

                            return;
                        }
                        method = item; // found single public(non-command) method.
                    }
                }

                if (method != null)
                {
                    goto RUN;
                }

                // completely not found, invalid command name show help.
                if (helpMethod != null)
                {
                    method = helpMethod;
                    goto RUN;
                }
                else
                {
                    Console.WriteLine(BatchEngine.BuildHelpParameter(methods));
                    return;
                }
            }
            catch (Exception ex)
            {
                await SetFailAsync(ctx, "Fail to get method. Type:" + type.FullName, ex);

                return;
            }

RUN:
            await RunCore(ctx, type, method, args, argsOffset);
        }
Exemple #9
0
 async ValueTask SetFailAsync(BatchContext context, string message, Exception ex)
 {
     Environment.ExitCode = 1;
     logger.LogError(ex, message);
     await interceptor.OnBatchRunCompleteAsync(context, message, ex);
 }
Exemple #10
0
        internal async Task RunAsync(Type type, string[] args)
        {
            logger.LogTrace("BatchEngine.Run Start");

            int        argsOffset = 0;
            MethodInfo method     = null;
            var        ctx        = new BatchContext(args, DateTime.UtcNow, cancellationToken, logger);

            try
            {
                await interceptor.OnBatchRunBeginAsync(ctx);

                if (type == typeof(void))
                {
                    await SetFailAsync(ctx, "Type or method does not found on this Program. args: " + string.Join(" ", args));

                    return;
                }

                var methods = type.GetMethods(BindingFlags.Public | BindingFlags.Instance | BindingFlags.DeclaredOnly);
                foreach (var item in methods)
                {
                    var command = item.GetCustomAttribute <CommandAttribute>();
                    if (command != null)
                    {
                        if (args.Length > 0 && command.CommandName.Equals(args[0], StringComparison.OrdinalIgnoreCase))
                        {
                            method     = item;
                            argsOffset = 1;
                            goto RUN;
                        }
                    }
                    else
                    {
                        if (method != null)
                        {
                            goto FAIL;
                        }
                        method = item;
                    }
                }

                if (method != null)
                {
                    goto RUN;
                }

FAIL:
                await SetFailAsync(ctx, "Method can not select. T of Run/UseBatchEngine<T> have to be contain single method or command. Type:" + type.FullName);

                return;
            }
            catch (Exception ex)
            {
                await SetFailAsync(ctx, "Fail to get method. Type:" + type.FullName, ex);

                return;
            }

RUN:
            await RunCore(ctx, type, method, args, argsOffset);
        }
Exemple #11
0
        async Task RunCore(BatchContext ctx, Type type, MethodInfo methodInfo, string[] args, int argsOffset)
        {
            object instance = null;

            object[] invokeArgs = null;

            try
            {
                if (!TryGetInvokeArguments(methodInfo.GetParameters(), args, argsOffset, out invokeArgs, out var errorMessage))
                {
                    await SetFailAsync(ctx, errorMessage + " args: " + string.Join(" ", args));

                    return;
                }
            }
            catch (Exception ex)
            {
                await SetFailAsync(ctx, "Fail to match method parameter on " + type.Name + "." + methodInfo.Name + ". args: " + string.Join(" ", args), ex);

                return;
            }

            try
            {
                instance = provider.GetService(type);
                typeof(BatchBase).GetProperty(nameof(BatchBase.Context)).SetValue(instance, ctx);
            }
            catch (Exception ex)
            {
                await SetFailAsync(ctx, "Fail to create BatchBase instance. Type:" + type.FullName, ex);

                return;
            }

            try
            {
                var result = methodInfo.Invoke(instance, invokeArgs);
                switch (result)
                {
                case int exitCode:
                    Environment.ExitCode = exitCode;
                    break;

                case Task <int> taskWithExitCode:
                    Environment.ExitCode = await taskWithExitCode;
                    break;

                case Task task:
                    await task;
                    break;
                }
            }
            catch (Exception ex)
            {
                if (ex is OperationCanceledException || ex is TaskCanceledException)
                {
                    return; // do nothing
                }

                if (ex is TargetInvocationException tex)
                {
                    await SetFailAsync(ctx, "Fail in batch running on " + type.Name + "." + methodInfo.Name, tex.InnerException);

                    return;
                }
                else
                {
                    await SetFailAsync(ctx, "Fail in batch running on " + type.Name + "." + methodInfo.Name, ex);

                    return;
                }
            }

            await interceptor.OnBatchRunCompleteAsync(ctx, null, null);

            logger.LogTrace("BatchEngine.Run Complete Successfully");
        }
 void SetFail(BatchContext context, string message, Exception ex)
 {
     Environment.ExitCode = 1;
     logger.LogError(ex, message);
     interceptor.OnBatchRunComplete(context, message, ex);
 }