Exemple #1
0
 void P_EnsireNotDisposeState()
 {
     if (vlt.Read(ref _disposeStateFlag) == __TrueFlag)
     {
         throw DisposableUtilities.NewObjectDisposedException(disposable: this, disposeRequestedException: false);
     }
     else
     {
         _disposableOwner.EnsureNotDisposeState(considerDisposeRequest: _considerDisposeRequest);
     }
 }
Exemple #2
0
 protected override void Dispose(bool explicitDispose)
 {
     if (explicitDispose)
     {
         _queueSpinLock?.EnterAndExitLock();
         var queue = _queue;
         if (queue != null && queue.Count > 0)
         {
             var exception = DisposableUtilities.NewObjectDisposedException(disposable: this, disposeRequestedException: false);
             queue.ForEach(action: locItem => locItem.TrySetException(exception: exception));
             queue.Clear();
         }
     }
     _queue         = null;
     _queueSpinLock = null;
     //
     base.Dispose(explicitDispose);
 }
Exemple #3
0
        // TODO: Put exception messages into the resources.
        //
        public ICsvDataTable Parse(TextReader inputTextReader)
        {
            if (inputTextReader == null)
            {
                throw new ArgumentNullException("inputTextReader");
            }
            P_Table table = null;
            var     rows  = new LinkedList <Row>();

            try {
                string textLine;
                string columnName;
                var    rowCtor          = default(Func <ICsvDataTable, IEnumerable <string>, Row>);
                var    textLineNumber   = 0;
                var    textLineValues   = new List <string>(48);
                var    columnNamesOrder = default(Dictionary <string, int>);
                for (;;)
                {
                    if (textLineNumber - 1 >= MaxRowCount)
                    {
                        throw new DigitalFlareApplicationException(string.Format("Источник данных содержит слишком много строк. Макс. допустимое количество строк '{0}'.", MaxRowCount.TextViewInvariant("d")));
                    }
                    textLine = inputTextReader.ReadLine();
                    if (textLine == null)
                    {
                        break;
                    }
                    textLineNumber++;
                    if (string.IsNullOrWhiteSpace(textLine))
                    {
                        throw new DigitalFlareApplicationException(string.Format("Несоответствие данных источника формату CSV. Данные, считанные из '{0}' строки источника представляют либо пустую строку, либо строку, содержащую только пробельные символы.", textLineNumber.TextViewInvariant("d")));
                    }
                    if (textLineNumber == 1)
                    {
                        // Table columns line.
                        //
                        textLineValues.Clear();
                        CsvUtilities.SplitLine(textLine, textLineNumber, textLineValues);
                        if (textLineValues.Count < 1)
                        {
                            throw new DigitalFlareApplicationException("Несоответствие данных источника формату CSV. Невозможно определить структуру CSV-таблицы.");
                        }
                        columnNamesOrder = new Dictionary <string, int>(ColumnNameEqualityComparer);
                        for (var i = 0; i < textLineValues.Count; i++)
                        {
                            columnName = textLineValues[i];
                            if (string.IsNullOrEmpty(columnName))
                            {
                                throw new DigitalFlareApplicationException(string.Format("Несоответствие данных источника формату CSV. Для колонки в '{0}' позиции не задано имя.", (i + 1).TextViewInvariant("d")));
                            }
                            if (columnName.Length > MaxColumnNameLength)
                            {
                                throw new DigitalFlareApplicationException(string.Format("Для колонки в '{0}' позиции задано слишком длинное имя. Макс. длина имени составляет '{1}' символов.", (i + 1).TextViewInvariant("d"), MaxColumnNameLength.TextViewInvariant("d")));
                            }
                            if (columnNamesOrder.ContainsKey(columnName))
                            {
                                throw new DigitalFlareApplicationException(string.Format("Несоответствие данных источника формату CSV. Для колонки в '{0}' позиции задано неуникальное имя '{1}'.", (i + 1).TextViewInvariant("d"), columnName.TextView()));
                            }
                            columnNamesOrder.Add(columnName, i);
                        }
                        table = new P_Table(P_GenerateRowType(columnNamesOrder, ColumnNameComparer), ColumnNameEqualityComparer);
                        table.Internal_SetColumns(columnNamesOrder.OrderBy(x => x.Value).Select(i => new P_Column(table, i.Key)));
                    }
                    else
                    {
                        // Table row line.
                        //
                        textLineValues.Clear();
                        CsvUtilities.SplitLine(textLine, textLineNumber, textLineValues);
                        if (textLineValues.Count != columnNamesOrder.Count)
                        {
                            throw new DigitalFlareApplicationException(string.Format("Несоответствие данных источника формату CSV. Строка данных (номер строки '{0}') не соответствует структуре таблицы по количеству колонок в таблице.", textLineNumber.TextViewInvariant("d")));
                        }
                        if (rowCtor == null)
                        {
                            rowCtor = ActivationUtilities.RequireConstructor <ICsvDataTable, IEnumerable <string>, Row>(concreteType: table.RowType);
                        }
                        rows.AddLast(rowCtor(table, textLineValues));
                    }
                }
                if (table == null)
                {
                    throw new DigitalFlareApplicationException("Источник данных не содержит какого-либо содержимого, на основе которого можно было бы создать CSV-таблицу.");
                }
                table.Internal_SetRows(rows);
                return(table);
            } catch (Exception firstException) {
                if (firstException.IsCritical())
                {
                    throw;
                }
                DisposableUtilities.Dispose(firstException, table);
                throw new DigitalFlareApplicationException("Во время создания CSV-таблицы из указанного источника данных возникла ошибка.", firstException);
            }
        }
Exemple #4
0
        // TODO: Put strings into the resources.
        //
        public virtual bool ResolveDependency <TDependency>(IDependencyResolutionContext ctx, out TDependency dependency)
            where TDependency : class
        {
            //
            ctx.EnsureNotNull(nameof(ctx));
            if (!ReferenceEquals(ctx.Scope, this))
            {
                throw
                    new ArgumentOutOfRangeException(
                        paramName: nameof(ctx),
                        message: $"Указанный контекст не принадлежит данной области функциональной зависимости.{Environment.NewLine}\tКонтекст:{ctx.FmtStr().GNLI2()}{Environment.NewLine}\tОбласть:{this.FmtStr().GNLI2()}");
            }
            else if (!typeof(TDependency).IsAssignableFrom(ctx.Specs.DependencyType))
            {
                throw
                    new ArgumentOutOfRangeException(
                        paramName: nameof(ctx),
                        message: $"Тип функциональной зависимости '{ctx.Specs.DependencyType}', определенный параметрами указанного контекста '{ctx}', не совместим с типом функциональной зависимости '{typeof(TDependency)}', указанным для данного вызова разрешения функциональной зависимости.");
            }
            //
            if (ctx.Specs.IsNewInstanceRequired && _prohibitNewInstanceRequest)
            {
                throw new EonException(message: $"Для данной области функциональной зависимости запрещены запросы на разрешение зависимости в новый экземпляр.{Environment.NewLine}\tОбласть:{this.FmtStr().GNLI2()}");
            }
#if DO_NOT_USE_EON_LOGGING_API
            if (ctx.IsAdvancedLoggingEnabled)
            {
                throw new NotSupportedException(message: $"В тек. версии расширенное логирование разрешения функциональной зависимости (см. {nameof(ctx)}.{nameof(ctx.IsAdvancedLoggingEnabled)}) не поддерживается.").SetErrorCode(code: GeneralErrorCodes.Operation.NotSupported);
            }
#else
            var isContextAdvancedLoggingEnabled = ctx.IsAdvancedLoggingEnabled;
#endif
            //
            var ensureResolution      = ctx.Specs.EnsureResolution;
            var isNewInstanceRequired = ctx.Specs.IsNewInstanceRequired;
            var selectCriterion       = ctx.Specs.SelectCriterion;
            var errorMessagePrologue  = $"Было затребовано разрешение функциональной зависимости.{Environment.NewLine}Функциональная зависимость:{Environment.NewLine}{typeof(TDependency).FmtStr().G().IndentLines()}{Environment.NewLine}Параметры разрешения:{Environment.NewLine}{ctx.Specs.ToString().IndentLines()}.";
            //
            List <IDependencyHandler2> currentScopeHandlersTraversal;
            IDependencyHandler2        currentHandler;
            object      resultDependencyInstanceAsObject;
            IDisposable resultInstanceAsDisposable;
            var         resultInstance = default(TDependency);
            var         handlerResult  = DependencyResult.None;
            //
            var newDependencyInstancesDisposeRegistry = ctx.Specs.DisposeRegistry ?? ReadDA(ref _newDependencyInstancesDisposeRegistry);
            //
            var runningResolutionsSpinLock   = ReadDA(ref _runningResolutionsSpinLock);
            var runningResolutionsUniqueness = ReadDA(ref _runningResolutionsUniqueness);
            var runningResolutionsSequence   = ReadDA(ref _runningResolutionsSequence);
            //
            var involvedScopes = new HashSet <IDependencyScope>(comparer: ReferenceEqualityComparer <IDependencyScope> .Instance);
            try {
                // Регистрация выполнения запроса ф. зависимости.
                //
                runningResolutionsSpinLock
                .Invoke(
                    () => {
                    EnsureNotDisposeState();
                    //
                    if (runningResolutionsSequence.Count >= MaxCountOfRunningResolutions)
                    {
                        throw
                        new EonException(
                            message: $"{errorMessagePrologue}{Environment.NewLine}Для области функциональной зависимости достигнут предел '{MaxCountOfRunningResolutions}' максимального количества одновременно выполняющихся вызовов разрешения функциональной зависимости.{Environment.NewLine}\tОбласть функциональной зависимости:{this.FmtStr().GNLI2()}")
                        .SetErrorCode(DependencyErrorCodes.Fault);
                    }
                    else if (runningResolutionsUniqueness.Add(item: ctx))
                    {
                        runningResolutionsSequence.Add(item: ctx);
                    }
                    else
                    {
                        throw
                        new EonException(
                            message: $"{errorMessagePrologue}{Environment.NewLine}Указанный контекст уже используется другим вызовом разрешения функциональной зависимости в данной области функциональной зависимости.{Environment.NewLine}\tКонтекст:{ctx.FmtStr().GNLI2()}{Environment.NewLine}\tОбласть функциональной зависимости:{this.FmtStr().GNLI2()}")
                        .SetErrorCode(DependencyErrorCodes.Fault);
                    }
                });
                //
                var thisScope     = (IDependencyScope)this;
                var previousScope = default(IDependencyScope);
                foreach (var currentScope in thisScope.TreeNode().SelfAndAncestors(parentSelector: locItem => locItem.GetOuterScope()))
                {
                    if (!involvedScopes.Add(currentScope))
                    {
                        throw
                            new EonException(
                                message: $"{errorMessagePrologue}{Environment.NewLine}Указанная область функциональной зависимости в составе окружающих (внешних) областей для данной области повторяется, что недопустимо.{Environment.NewLine}\tДанная область:{this.FmtStr().GNLI2()}{Environment.NewLine}\tУказанная область:{this.FmtStr().GNLI2()}{Environment.NewLine}\tОбласть, предшествующая указанной:{previousScope.FmtStr().GNLI2()}")
                            .SetErrorCode(DependencyErrorCodes.Fault);
                    }
                    // Составить упорядоченный список обхода обработчиков запроса ф. зависимости.
                    //
                    currentScopeHandlersTraversal = new List <IDependencyHandler2>(collection: currentScope.GetResolutionModel());
                    if (involvedScopes.Count == 1)
                    {
                        // Сначала должны быть использованы обработчики запроса ф. зависимости первичной модели (если она задана), поэтому они добавляются в начало списка обхода.
                        //
                        var primaryModel = ctx.Specs.PrimaryResolutionModel.EmptyIfNull();
                        if (currentScopeHandlersTraversal.Count == 0)
                        {
                            currentScopeHandlersTraversal.AddRange(collection: primaryModel);
                        }
                        else
                        {
                            currentScopeHandlersTraversal.InsertRange(index: 0, collection: primaryModel);
                        }
                        //
                        previousScope = currentScope;
                    }
                    // Обход списка обработчиков запроса ф. зависимости.
                    //
                    var currentHandlerIndex    = 0;
                    var handlerRedirectCounter = 0;
                    for (; resultInstance is null && currentHandlerIndex < currentScopeHandlersTraversal.Count;)
                    {
                        currentHandler = currentScopeHandlersTraversal[currentHandlerIndex];
                        //
                        if (currentHandler != null && ctx.TryInvolveHandler(handler: currentHandler))
                        {
                            resultInstanceAsDisposable = (resultDependencyInstanceAsObject = (handlerResult = currentHandler.ExecuteResolution(resolutionCtx: ctx)).Instance) as IDisposable;
                            if (resultDependencyInstanceAsObject is null)
                            {
                                if (!(handlerResult.RedirectHandler is null))
                                {
                                    if (handlerRedirectCounter++ < DefaultOfMaxCountOfResolutionRedirect)
                                    {
                                        var redirectHandlerIndex = currentHandlerIndex + 1;
                                        if (redirectHandlerIndex < currentScopeHandlersTraversal.Count)
                                        {
                                            currentScopeHandlersTraversal.Insert(index: redirectHandlerIndex, item: handlerResult.RedirectHandler);
                                        }
                                        else
                                        {
                                            currentScopeHandlersTraversal.Add(item: handlerResult.RedirectHandler);
                                        }
                                    }
                                    else
                                    {
                                        throw
                                            new EonException(
                                                message: $"Dependency resolution was broken due to the count of dependency handlers redirects reached the limit — {DefaultOfMaxCountOfResolutionRedirect:d} (see {nameof(DependencyScope)}.{nameof(DefaultOfMaxCountOfResolutionRedirect)}).{Environment.NewLine}Redirect from handler:{currentHandler.FmtStr().GNLI2()}{Environment.NewLine}Redirect to handler:{handlerResult.RedirectHandler.FmtStr().GNLI2()}{Environment.NewLine}Scope:{currentScope.FmtStr().GNLI2()}")
                                            .SetErrorCode(code: DependencyErrorCodes.Fault);
                                    }
                                }
                            }
                            else if ((resultInstance = resultDependencyInstanceAsObject as TDependency) is null)
                            {
                                throw
                                    new EonException(
                                        $"{errorMessagePrologue}{Environment.NewLine}Компонент, исполняющий разрешение функциональной зависимости, возвратил недопустимый результат. Тип '{resultDependencyInstanceAsObject.GetType()}' экземпляра, полученного от компонента, не совместим с требуемым типом '{typeof(TDependency)}'.{Environment.NewLine}\tКомпонент:{currentHandler.FmtStr().GNLI2()}")
                                    .SetErrorCode(DependencyErrorCodes.Fault);
                            }
                            else if (ctx.Specs.IsNewInstanceRequired && !handlerResult.IsNewInstance)
                            {
                                throw
                                    new EonException(
                                        $"{errorMessagePrologue}{Environment.NewLine}Компонент, исполняющий разрешение функциональной зависимости, возвратил недопустимый результат. От компонента было затребовано создание нового экземпляра, но компонент возвратил результат, указывающий, что экземпляр не является новым.{Environment.NewLine}\tКомпонент:{currentHandler.FmtStr().GNLI2()}")
                                    .SetErrorCode(DependencyErrorCodes.Fault);
                            }
                            else if (!ctx.IsMatchSelectCriterion(resultInstance))
                            {
                                if (handlerResult.IsNewInstance)
                                {
                                    resultInstanceAsDisposable?.Dispose();
                                }
                                resultInstanceAsDisposable       = null;
                                resultDependencyInstanceAsObject = null;
                                resultInstance = null;
                            }
                            else if (handlerResult.IsNewInstance && resultInstanceAsDisposable != null)
                            {
                                newDependencyInstancesDisposeRegistry.Register(resultInstanceAsDisposable);
                            }
                        }
                        //
#if !DO_NOT_USE_EON_LOGGING_API
                        if (isContextAdvancedLoggingEnabled && !(resultDependencyInstance is null))
                        {
                            string loggingInformationMessage;
                            using (var acquiredBuffer = StringBuilderUtilities.AcquireBuffer()) {
                                var sb = acquiredBuffer.StringBuilder;
                                sb.AppendLine($"Функциональная зависимость разрешена.");
                                sb.AppendLine($"\tПараметры разрешения:");
                                sb.AppendLine(ctx.Specs.ToString().IndentLines(indentSize: 2));
                                sb.AppendLine($"\tЭкземпляр зависимости:");
                                sb.Append(resultDependencyInstance.ToString().IndentLines(indentSize: 2));
                                loggingInformationMessage = sb.ToString();
                            }
                            context.IssueInformation($"Разрешение функциональной зависимости (ИД контекста '{contextSequentialId:d}').", loggingInformationMessage);
                        }
#endif
                        //
                        currentHandlerIndex++;
                    }
                    //
                    if (resultInstance != null)
                    {
                        break;
                    }
                }
            }
            catch (Exception exception) {
                if (handlerResult.IsNewInstance)
                {
                    DisposableUtilities.DisposeMany(exception, handlerResult.Instance as IDisposable);
                }
                throw;
            }
            finally {
                runningResolutionsSpinLock
                .Invoke(
                    () => {
                    if (!(Disposing || IsDisposed))
                    {
                        runningResolutionsSequence.RemoveAll(match: locItem => ReferenceEquals(objA: locItem, objB: ctx));
                        runningResolutionsUniqueness.Remove(item: ctx);
                    }
                });
            }
            //
            if (resultInstance is null)
            {
                if (ensureResolution)
                {
                    // Формирование текста сообщения ошибки.
                    //
                    // TODO: involvedExecutorsChainShowReportMaxCount сделать конфигурируемым.
                    //
                    var    involvedExecutorsChainShowReportMaxCount = FormatStringUtilities.DefaultMaxCountOfCollectionOutputItems;
                    string involvedExecutorsChainReport;
                    IDependencyHandler2[] involvedHandlerChain;
                    string involvedHandlerText(IDependencyHandler2 locHandler)
                    => $"Объект:{locHandler.FmtStr().GNLI()}";

                    using (var buffer = EonStringBuilderUtilities.AcquireBuffer()) {
                        var sb = buffer.StringBuilder;
                        involvedHandlerChain = ctx.GetInvolvedHandlerChain();
                        var involvedExecutorsChainLimit = Math.Min(involvedExecutorsChainShowReportMaxCount, involvedHandlerChain.Length);
                        for (var k = 0; k < involvedExecutorsChainLimit; k++)
                        {
                            if (k > 0)
                            {
                                sb.AppendLine();
                            }
                            sb.Append($"{(k + 1):d}) {involvedHandlerText(involvedHandlerChain[ k ])}");
                        }
                        if (involvedHandlerChain.Length > involvedExecutorsChainShowReportMaxCount)
                        {
                            if (involvedHandlerChain.Length - involvedExecutorsChainShowReportMaxCount < 3)
                            {
                                sb.Append($"{Environment.NewLine}{(involvedExecutorsChainShowReportMaxCount + 1):d}) {involvedHandlerText(involvedHandlerChain[ involvedExecutorsChainShowReportMaxCount ])}");
                            }
                            else
                            {
                                sb.Append($"{Environment.NewLine}…");
                            }
                            //
                            if (involvedHandlerChain.Length > (involvedExecutorsChainShowReportMaxCount + 1))
                            {
                                sb.Append($"{Environment.NewLine}{(involvedHandlerChain.Length):d}) {involvedHandlerText(involvedHandlerChain[ involvedHandlerChain.Length - 1 ])}");
                            }
                        }
                        involvedExecutorsChainReport = sb.ToString();
                    }
                    throw
                        new EonException(
                            $"{errorMessagePrologue}{Environment.NewLine}Указанная зависимость не была разрешена.{Environment.NewLine}Детали:{Environment.NewLine}\tОбласть функциональной зависимости:{Environment.NewLine}{this.FmtStr().GI2()}{Environment.NewLine}\tПоследовательность задействованных обработчиков (длина {involvedHandlerChain.Length:d}):{Environment.NewLine}{involvedExecutorsChainReport.IndentLines2()}")
                        .SetErrorCode(DependencyErrorCodes.Resolution_NotResolved);
                }
                else
                {
                    dependency = null;
                    return(false);
                }
            }
            else
            {
                dependency = resultInstance;
                return(true);
            }
        }