コード例 #1
0
 protected override Task <DependencyResult <TDependencyInstance> > ResolveNewDependencyInstanceAsync(IDependencyResolutionContext context)
 {
     try {
         var specs = context.EnsureNotNull(nameof(context)).Value.Specs;
         //
         var factoryArgs = ReadDA(ref _factoryArgs);
         if (factoryArgs is null)
         {
             // Поскольку в данном обработчике явно не заданы параметры конструктора нового экземпляра, используются те, что указаны в спецификации, если они подходят для использования (см. код ниже).
             //
             if ((factoryArgs = specs.NewInstanceFactoryArgs as IArgsTuple <TArg1>) == null || factoryArgs.ArgsCount != __ArgsCount)
             {
                 return(TaskUtilities.FromResult(DependencyResult <TDependencyInstance> .None));
             }
         }
         else if (!(specs.NewInstanceFactoryArgs is null))
         {
             // Поскольку спецификацией явно определены параметры конструктора нового экземпляра, а также явно заданны в данном обработчике (factoryArgs != null), то получается конфликт.
             //
             return(TaskUtilities.FromResult(DependencyResult <TDependencyInstance> .None));
         }
         return
             (TaskUtilities
              .FromResult(
                  result:
                  new DependencyResult <TDependencyInstance>(
                      instance: ReadDA(ref _getDependencyCtor)()(factoryArgs.Arg1),
                      isNewInstance: true)));
     }
     catch (Exception exception) {
         return(Task.FromException <DependencyResult <TDependencyInstance> >(exception));
     }
 }
コード例 #2
0
 protected override Task <DependencyResult <TDependencyInstance> > ResolveNewDependencyInstanceAsync(IDependencyResolutionContext context)
 {
     try {
         var specs = context.EnsureNotNull(nameof(context)).Value.Specs;
         //
         var factoryArgs = ReadDA(ref _factoryArgs);
         if (factoryArgs is null)
         {
             if ((factoryArgs = specs.NewInstanceFactoryArgs as IArgsTuple <TArg1, TArg2, TArg3, TArg4, TArg5>) == null || factoryArgs.ArgsCount != __ArgsCount)
             {
                 return(TaskUtilities.FromResult(DependencyResult <TDependencyInstance> .None));
             }
         }
         else if (specs.NewInstanceFactoryArgs != null)
         {
             return(TaskUtilities.FromResult(DependencyResult <TDependencyInstance> .None));
         }
         //
         return
             (TaskUtilities
              .FromResult(
                  result:
                  new DependencyResult <TDependencyInstance>(
                      instance:
                      ReadDA(ref _getDependencyCtor)
                          ()
                          (factoryArgs.Arg1, factoryArgs.Arg2, factoryArgs.Arg3, factoryArgs.Arg4, factoryArgs.Arg5),
                      isNewInstance: true)));
     }
     catch (Exception exception) {
         return(Task.FromException <DependencyResult <TDependencyInstance> >(exception));
     }
 }
コード例 #3
0
            TEfDbContext P_GetDataChangeEfDbContext()
            {
                var result = ReadDA(ref _efCtxGetter, considerDisposeRequest: true)();

                EnsureNotDisposeState(considerDisposeRequest: true);
                return(result);
            }
コード例 #4
0
 protected override Task <DependencyResult <TDependencyInstance> > ResolveNewDependencyInstanceAsync(IDependencyResolutionContext context)
 {
     try {
         var specs = context.EnsureNotNull(nameof(context)).Value.Specs;
         //
         if ((specs.NewInstanceFactoryArgs?.ArgsCount ?? 0) != __ArgsCount)
         {
             return(TaskUtilities.FromResult(DependencyResult <TDependencyInstance> .None));
         }
         else
         {
             return
                 (TaskUtilities
                  .FromResult(
                      result:
                      new DependencyResult <TDependencyInstance>(
                          instance: ReadDA(ref _getDependencyCtor, considerDisposeRequest: true)()(),
                          isNewInstance: true)));
         }
     }
     catch (Exception exception) {
         return(Task.FromException <DependencyResult <TDependencyInstance> >(exception));
     }
 }
コード例 #5
0
        // TODO: Put strings into the resources.
        //
        public Task <IRunControlAttemptSuccess> StartAsync(IContext ctx = default)
        {
            try {
                var component = Component;
                if ((Options & RunControlOptions.ForbidStart) == RunControlOptions.ForbidStart)
                {
                    throw new EonException(message: $"Опциями элемента управления запуском/остановкой компонента, запрещено выполнение операции запуска.{Environment.NewLine}\tКомпонент:{component.FmtStr().GNLI2()}");
                }
                else
                {
                    return(TaskUtilities.RunOnDefaultScheduler(factory: doStartAsync));
                }
            }
            catch (Exception exception) {
                return(Task.FromException <IRunControlAttemptSuccess>(exception: exception));
            }
            //
            async Task <IRunControlAttemptSuccess> doStartAsync()
            {
                ctx.ThrowIfCancellationRequested();
                var ctxCt           = ctx.Ct();
                var existingStartOp = default(RunControlStartOperationState <TComponent>);
                var newStartOp      = default(RunControlStartOperationState <TComponent>);
                var component       = Component;
                var begimTimestamp  = StopwatchUtilities.GetTimestampAsTimeSpan();

                try {
                    UpdDABool(
                        location: ref _existingStartOp,
                        transform:
                        (locCurrent, locPrevious) => {
                        if (locCurrent is null)
                        {
                            return(locPrevious ?? (newStartOp = new RunControlStartOperationState <TComponent>(runControl: this, beginTimestamp: begimTimestamp, ct: ctxCt)));
                        }
                        else
                        {
                            return(locCurrent);
                        }
                    },
                        current: out existingStartOp);
                    if (ReferenceEquals(newStartOp, existingStartOp))
                    {
                        // Поток (задача), который непосредственно выполняет запуск.
                        //
                        if (!itrlck.IncrementBool(location: ref _startOpAttemptNumber, maxInclusive: int.MaxValue, result: out var attemptNumber))
                        {
                            throw
                                new EonException(message: $"Невозможно присвоить операции последовательный номер попытки. Счётчик попыток достиг предельного значения.{Environment.NewLine}\tКомпонент:{component.FmtStr().GNLI2()}");
                        }
                        // Если выполняется операция остановки, то дождаться её завершения.
                        //
                        var existingStopOp = itrlck.Get(ref _existingStopOp);
                        if (!(existingStopOp is null))
                        {
                            try {
                                await existingStopOp.Completion.WaitCompletionAsync(ct : ctxCt).ConfigureAwait(false);
                            }
                            catch (Exception exception) {
                                if (exception.HasSingleBaseExceptionOf <OperationCanceledException>(out var operationCancellationException))
                                {
                                    itrlck.SetNullBool(ref _existingStartOp, comparand: newStartOp);
                                    newStartOp.TrySetCanceled(ct: operationCancellationException.CancellationToken);
                                }
                                throw;
                            }
                            try {
                                await existingStopOp.Completion.ConfigureAwait(false);
                            }
                            catch (Exception exception) when(exception.HasSingleBaseExceptionOf <OperationCanceledException>())
                            {
                                throw
                                    new EonException(
                                        message: $"Невозможно выполнить запуск компонента, так как ранее для компонента была инициирована операция остановки, которая была прервана или отменена.{Environment.NewLine}\tКомпонент:{component.FmtStr().GNLI2()}");
                            }
                            catch (Exception exception) {
                                throw
                                    new EonException(
                                        message: $"Невозможно выполнить запуск компонента, так как ранее для компонента была инициирована операция остановки, которая завершилась сбоем. Детали сбоя см. во внутреннем стеке данного исключения.{Environment.NewLine}\tКомпонент:{component.FmtStr().GNLI2()}",
                                        innerException: exception);
                            }
                            if ((Options & RunControlOptions.MultipleStart) == RunControlOptions.MultipleStart)
                            {
                                if (existingStopOp.FiniteStop)
                                {
                                    newStartOp.TrySetCanceled();
                                    throw
                                        new OperationCanceledException(
                                            message: $"Запуск компонента отменён, так как ранее поступил запрос остановки компонента без возможности перезапуска.{Environment.NewLine}\tКомпонент:{component.FmtStr().GNLI2()}");
                                }
                                else if (!itrlck.SetNullBool(ref _existingStopOp, comparand: existingStopOp))
                                {
                                    throw
                                        new EonException(
                                            message: $"Не удалось привести управляющий элемент запуска/остановки компонента к предстартовому состоянию.{Environment.NewLine}\tКомпонент:{component.FmtStr().GNLI2()}");
                                }
                            }
                            else
                            {
                                newStartOp.TrySetCanceled();
                                throw
                                    new OperationCanceledException(
                                        message: $"Запуск компонента отменён, так как ранее поступил запрос остановки компонента и опциями элемента, управляющего запуском/остановкой компонента, не определена возможность многократного запуска компонента.{Environment.NewLine}\tКомпонент:{component.FmtStr().GNLI2()}");
                            }
                        }
                        // Запуск.
                        //
                        IContext locCtx = default;
                        try {
                            try {
                                locCtx = P_CreateStartCtx(startOp: newStartOp, outerCtx: ctx);
                                newStartOp.AttemptState =
                                    ReadDA(ref _attemptStateFactory)
                                        (args:
                                        new RunControlAttemptStateFactoryArgs(
                                            runControl: this,
                                            completion: newStartOp.Completion,
                                            context: locCtx,
                                            isStart: true,
                                            attemptNumber: attemptNumber,
                                            succeededAttemptCountBefore: vlt.Read(ref _startOpSucceededCount)));
                            }
                            catch (Exception exception) {
                                if (exception.HasSingleBaseExceptionOf <OperationCanceledException>(baseException: out var operationCancellationException))
                                {
                                    itrlck.SetNullBool(location: ref _existingStartOp, comparand: newStartOp);
                                    newStartOp.TrySetCanceled(ct: operationCancellationException.CancellationToken);
                                }
                                throw;
                            }
                            // Процедура предзапуска.
                            //
                            try {
                                locCtx.ThrowIfCancellationRequested();
                                await P_BeforeStartAsync(state : newStartOp.AttemptState).ConfigureAwait(false);
                            }
                            catch (Exception exception) {
                                itrlck.SetNullBool(ref _existingStartOp, comparand: newStartOp);
                                if (exception.HasSingleBaseExceptionOf <OperationCanceledException>(out var operationCancellationException))
                                {
                                    newStartOp.TrySetCanceled(ct: operationCancellationException.CancellationToken);
                                    throw;
                                }
                                else
                                {
                                    throw new EonException(message: $"Сбой во время процедуры предзапуска компонента.{Environment.NewLine}\tКомпонент:{component.FmtStr().GNLI2()}", innerException: exception);
                                }
                            }
                            // Процедура запуска.
                            //
                            try {
                                locCtx.ThrowIfCancellationRequested();
                                var startTask = ReadDA(ref _startTaskFactory)(arg : newStartOp.AttemptState);
                                if (startTask is null)
                                {
                                    throw new EonException(message: $"Невозможно выполнить операцию запуска компонента, так как функция создания задачи выполнения запуска возвратила недопустимый результат '{startTask.FmtStr().G()}'.{Environment.NewLine}\tКомпонент:{component.FmtStr().GNLI2()}");
                                }
                                await startTask.ConfigureAwait(false);
                            }
                            catch (Exception exception) {
                                if (exception.HasSingleBaseExceptionOf <OperationCanceledException>(out var operationCancellationException))
                                {
                                    itrlck.SetNullBool(ref _existingStartOp, comparand: newStartOp);
                                    newStartOp.TrySetCanceled(ct: operationCancellationException.CancellationToken);
                                    throw;
                                }
                                else
                                {
                                    throw new EonException(message: $"Сбой во время запуска компонента.{Environment.NewLine}\tКомпонент:{component.FmtStr().GNLI2()}", innerException: exception);
                                }
                            }
                            itrlck.IncrementBool(location: ref _startOpSucceededCount, maxInclusive: int.MaxValue);
                            var result = newStartOp.SetSucceeded(isMaster: true);
                            P_TryFireAfterStartAsynchronously(result: result);
                            return(result);
                        }
                        finally {
                            locCtx?.Dispose();
                        }
                    }
                    else
                    {
                        newStartOp?.TrySetCanceled(synchronously: true);
                        // TODO_HIGH: Возможно, нужно обрабатывать такую ситуацию, когда данный вызов получит результат в виде отменённой операции, потому что уже выполняющий другой вызов был отменён. Такая ситуация с точки зрения вызывающий стороны не совсем очевидна и предсказуема.
                        // + нужно реализовать трансляцию хода выполнения из уже выполняющегося вызова в данный.
                        //
                        if (ctxCt == existingStartOp.Ct)
                        {
                            // Один и тот же токен отмены из разных вызовов.
                            //
                            return(new RunControlAttemptSuccess(other: await existingStartOp.Completion.ConfigureAwait(false), isMaster: false));
                        }
                        else
                        {
                            return(new RunControlAttemptSuccess(other: await existingStartOp.Completion.WaitResultAsync(ct: ctxCt).ConfigureAwait(false), isMaster: false));
                        }
                    }
                }
                catch (Exception exception) {
                    if (ReferenceEquals(existingStartOp, newStartOp) && !(newStartOp is null))
                    {
                        if (newStartOp.TrySetException(exception: exception, synchronously: true))
                        {
                            // Здесь будет вызвано исключение.
                            //
                            await newStartOp.Completion;
                        }
                        throw;
                    }
                    else
                    {
                        throw;
                    }
                }
                finally {
                    if (!ReferenceEquals(existingStartOp, newStartOp))
                    {
                        newStartOp?.TrySetCanceled(synchronously: true);
                    }
                }
            }
        }
コード例 #6
0
 public IDependencyScope GetOuterScope()
 => ReadDA(ref _outerScopeGetter)();
コード例 #7
0
 public virtual IEnumerable <IVh <IDependencyHandler2> > ExportDependencies()
 => ReadDA(location: ref _exportDependencies)();
コード例 #8
0
 public IEnumerable <IVh <IDependencyHandler2> > ExportDependencies()
 => ReadDA(ref _export)();