void P_EnsireNotDisposeState() { if (vlt.Read(ref _disposeStateFlag) == __TrueFlag) { throw DisposableUtilities.NewObjectDisposedException(disposable: this, disposeRequestedException: false); } else { _disposableOwner.EnsureNotDisposeState(considerDisposeRequest: _considerDisposeRequest); } }
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); }
// 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); } }
// 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); } }