コード例 #1
0
 public static KeyValuePair <string, string> CreateFrom(Exception exception, string delimiter = default)
 {
     exception.EnsureNotNull(nameof(exception));
     //
     delimiter = delimiter ?? " ";
     using (var acquiredBuffer = EonStringBuilderUtilities.AcquireBuffer()) {
         var stringBuilder = acquiredBuffer.StringBuilder;
         //
         var notFirstCode = false;
         foreach (var errorCode in exception.FlattenBase(selector: locException => locException.HasErrorCode()).InnerExceptions.Select(e => e.GetErrorCode()))
         {
             if (notFirstCode)
             {
                 stringBuilder.Append(delimiter);
             }
             else
             {
                 notFirstCode = true;
             }
             //
             stringBuilder.Append(errorCode.Identifier);
         }
         //
         return(new KeyValuePair <string, string>(Name, stringBuilder.ToString()));
     }
 }
コード例 #2
0
 public static string ConcatStrings(this IEnumerable <string> strs, string separator, bool skipEmptyStrings)
 {
     if (strs is null)
     {
         return(null);
     }
     else
     {
         using (var buffer = EonStringBuilderUtilities.AcquireBuffer()) {
             var sb = buffer.StringBuilder;
             if (skipEmptyStrings)
             {
                 strs = strs.Where(locString => !string.IsNullOrEmpty(locString));
             }
             var notFirstString = false;
             foreach (var @string in strs)
             {
                 if (notFirstString)
                 {
                     sb.Append(separator);
                 }
                 else
                 {
                     notFirstString = true;
                 }
                 sb.Append(@string);
             }
             //
             return(sb.ToString());
         }
     }
 }
コード例 #3
0
        // TODO: Put strings into the resources.
        //
        public static string FormatCommandLineArgs()
        {
            string[] args;
            var      notSupported = false;

            try { args = Environment.GetCommandLineArgs(); }
            catch (NotSupportedException) { args = null; notSupported = true; }
            if (notSupported)
            {
                return("<не поддерживается>");
            }
            else if (args.IsNullOrEmpty())
            {
                return("<отсутсвуют>");
            }
            else
            {
                using (var acquiredBuffer = EonStringBuilderUtilities.AcquireBuffer()) {
                    var sb = acquiredBuffer.StringBuilder;
                    sb.Append(args[0]);
                    for (var i = 1; i < args.Length; i++)
                    {
                        sb.Append(Environment.NewLine);
                        sb.Append('\t');
                        sb.Append(args[i]);
                    }
                    return(sb.ToString());
                }
            }
        }
コード例 #4
0
 // TODO: Put strings into the resources.
 //
 public static string GCollection <T>(this FormatStringUtilitiesHandle <ICollection <T> > hnd, int maxCountOfOutputItems, IFormatProvider formatProvider, Func <int, T, IFormatProvider, string> itemFormatter)
 {
     maxCountOfOutputItems
     .Arg(nameof(maxCountOfOutputItems))
     .EnsureNotLessThanZero();
     //
     if (hnd.Object == null)
     {
         return(FormatStringUtilities.GetNullValueText(formatProvider: formatProvider));
     }
     else
     {
         if (itemFormatter == null)
         {
             itemFormatter = (locIndex, locItem, locFormatProvider) => locItem.FmtStr().G(formatProvider: formatProvider);
         }
         using (var acquiredBuffer = EonStringBuilderUtilities.AcquireBuffer()) {
             var outputBuilder = acquiredBuffer.StringBuilder;
             //
             var collectionSize = hnd.Object.Count;
             outputBuilder.Append($"Коллекция (размер {collectionSize.ToString("d", formatProvider)}):");
             if (maxCountOfOutputItems > 0)
             {
                 var itemCounter = 0;
                 foreach (var item in hnd.Object)
                 {
                     checked { itemCounter++; }
                     outputBuilder.Append(Environment.NewLine);
                     outputBuilder.Append('\x0009');
                     outputBuilder.Append(itemCounter.ToString("d", formatProvider));
                     outputBuilder.Append(")");
                     outputBuilder
                     .Append(
                         value:
                         itemFormatter(arg1: itemCounter - 1, arg2: item, arg3: formatProvider)
                         .FmtStr()
                         .G(formatProvider: formatProvider)
                         .FmtStr()
                         .GNLI2());
                     if (itemCounter == maxCountOfOutputItems)
                     {
                         break;
                     }
                 }
             }
             if (collectionSize > maxCountOfOutputItems)
             {
                 outputBuilder.Append(Environment.NewLine);
                 outputBuilder.Append('\x0009');
                 outputBuilder.Append('…');
             }
             //
             return(outputBuilder.ToString());
         }
     }
 }
コード例 #5
0
 // TODO: Put strings into the resources.
 //
 public override string ToString()
 {
     using (var acquiredBuffer = EonStringBuilderUtilities.AcquireBuffer()) {
         var sb = acquiredBuffer.StringBuilder;
         //
         sb.Append($"{GetType().FmtStr().G()}:");
         sb.Append($"{Environment.NewLine}\tТип зависимости:{(_dependencyType?.AssemblyQualifiedName ?? "-").FmtStr().GNLI2()}");
         sb.Append($"{Environment.NewLine}\tНовый экземпляр зависимости:{_isNewInstanceRequired.FmtStr().YesNo().FmtStr().GNLI2()}");
         sb.Append($"{Environment.NewLine}\tТребуемый конструктор экземпляра зависимости:{(_newInstanceFactoryArgs?.ToString() ?? "-").FmtStr().GNLI2()}");
         sb.Append($"{Environment.NewLine}\tКритерий выбора экземпляра зависимости:{(_selectCriterion?.ToString() ?? "-").FmtStr().GNLI2()}");
         sb.Append($"{Environment.NewLine}\t1-ый обработчик первичной модели разрешения:{(_primaryResolutionModel?.FirstOrDefault()?.ToString() ?? "-").FmtStr().GNLI2()}");
         return(sb.ToString());
     }
 }
コード例 #6
0
 public static string EscapeInvalidFileNameChars(string fileName)
 {
     if (string.IsNullOrEmpty(fileName))
     {
         return(fileName);
     }
     using (var buf = EonStringBuilderUtilities.AcquireBuffer()) {
         var sb = buf.StringBuilder;
         sb.Append(fileName);
         for (var i = 0; i < __InvalidFileNameChars.Length; i++)
         {
             sb.Replace(__InvalidFileNameChars[i], InvalidPathCharEscapeChar);
         }
         return(sb.ToString());
     }
 }
コード例 #7
0
 public static string RemoveHyphens(string value)
 {
     if (string.IsNullOrWhiteSpace(value))
     {
         return(value);
     }
     else
     {
         using (var acquiredBuffer = EonStringBuilderUtilities.AcquireBuffer()) {
             var sb = acquiredBuffer.StringBuilder;
             //
             var previousChar = '-';
             for (var i = 0; i < value.Length; i++)
             {
                 var currentChar = value[i];
                 if (currentChar != '-')
                 {
                     if (previousChar == '-')
                     {
                         if (i + 1 < value.Length && char.IsUpper(value[i + 1]))
                         {
                             sb.Append(currentChar);
                         }
                         else
                         {
                             sb.Append(char.ToUpper(currentChar));
                         }
                     }
                     else
                     {
                         sb.Append(currentChar);
                     }
                 }
                 //
                 previousChar = currentChar;
             }
             //
             return(sb.ToString());
         }
     }
 }
コード例 #8
0
 public override string ToString()
 {
     using (var stringBuilderBuffer = EonStringBuilderUtilities.AcquireBuffer()) {
         var sb = stringBuilderBuffer.StringBuilder;
         sb.Append((TargetType?.Type).FmtStr());
         sb.Append(' ');
         sb.Append(ConstructorInfo.ConstructorName);
         sb.Append('(');
         var ctorSignatureArgIndex = -1;
         foreach (var ctorSignatureArg in ConstructorSignature.EmptyIfNull())
         {
             if (++ctorSignatureArgIndex > 0)
             {
                 sb.Append(", ");
             }
             sb.Append((ctorSignatureArg?.Type).FmtStr().G());
         }
         sb.Append(')');
         return(sb.ToString());
     }
 }
コード例 #9
0
 public static string RepeatString(this string @string, int count)
 {
     count
     .Arg(nameof(count))
     .EnsureNotLessThanZero();
     //
     if (string.IsNullOrEmpty(@string) || count < 1)
     {
         return(@string);
     }
     else
     {
         using (var acquiredBuffer = EonStringBuilderUtilities.AcquireBuffer()) {
             var sb = acquiredBuffer.StringBuilder;
             sb.Append(@string);
             for (var i = 0; i < count; i++)
             {
                 sb.Append(@string);
             }
             return(sb.ToString());
         }
     }
 }
コード例 #10
0
 public static string SerializeToJson <T>(this T @object, JsonSerializer serializer, bool indent)
 {
     @object.EnsureNotNull(nameof(@object));
     serializer.EnsureNotNull(nameof(serializer));
     //
     using (var acquiredBuffer = EonStringBuilderUtilities.AcquireBufferUnlimCapacity())
         using (var stringWriter = new StringWriter(sb: acquiredBuffer.StringBuilder))
             using (var jsonWriter = new JsonTextWriter(textWriter: stringWriter)) {
                 if (indent)
                 {
                     jsonWriter.Formatting  = Formatting.Indented;
                     jsonWriter.Indentation = 1;
                     jsonWriter.IndentChar  = '\x0009';
                 }
                 else
                 {
                     jsonWriter.Formatting = Formatting.None;
                 }
                 serializer.Serialize(jsonWriter, @object);
                 jsonWriter.Flush();
                 return(acquiredBuffer.StringBuilder.ToString());
             }
 }
コード例 #11
0
 public static IFormattable ToFormattableString(this IEnumerable <IFormattable> strs, string separator)
 {
     if (strs is null)
     {
         return(null);
     }
     else
     {
         string format;
         var    args = new List <object>();
         using (var buffer = EonStringBuilderUtilities.AcquireBuffer()) {
             var stringBuilder = buffer.StringBuilder;
             foreach (var @string in strs)
             {
                 if (@string == null)
                 {
                     continue;
                 }
                 else if (stringBuilder.Length > 0)
                 {
                     stringBuilder.Append(separator);
                 }
                 stringBuilder.Append("{" + args.Count.ToString("d", CultureInfo.InvariantCulture) + "}");
                 args.Add(@string);
             }
             format = stringBuilder.ToString();
         }
         if (format == string.Empty)
         {
             return(new Globalization.FormattableString());
         }
         else
         {
             return(new Globalization.FormattableString(format: format, args: args.ToArray()));
         }
     }
 }
コード例 #12
0
 /// <summary>
 /// Вставляет отступ в начале каждой новой строки текста <paramref name="inputText"/>.
 /// <para>Если значение <paramref name="inputText"/> равно null или <see cref="string.Empty"/>, то метод возвратит значение <paramref name="inputText"/>.</para>
 /// </summary>
 /// <param name="inputText">Входной текст.</param>
 /// <param name="lineSeparator">
 /// Строка, определяющая разделитель строк в <paramref name="inputText"/>.
 /// <para>Если значение не задано или равно null, то будет использоваться значение <see cref="Environment.NewLine"/>.</para>
 /// </param>
 /// <param name="indent">
 /// Строка, определяющая отступ в начале каждой новой строки <paramref name="inputText"/>.
 /// <para>Если значение не задано или равно null, то будет использоваться символ табуляции (\u0009).</para>
 /// </param>
 /// <param name="indentSize">
 /// Размер отступа.
 /// <para>Если не задан или равен null, то будет использоваться значение 1.</para>
 /// </param>
 /// <param name="inputTextSplitOptions">
 /// Опции разбиения входного текста <paramref name="inputText"/> на строки.
 /// <para>Если не задан или равен null, то будет использоваться значение <see cref="StringSplitOptions.None"/>.</para>
 /// </param>
 /// <param name="skipFirstLine">
 /// Указывает, оставить ли первую строку текста <paramref name="inputText"/> без отступа.
 /// </param>
 /// <returns>
 /// Объект <see cref="string"/>.
 /// </returns>
 public static string IndentLines(
     this string inputText,
     string lineSeparator = null,
     string indent        = null,
     int?indentSize       = null,
     StringSplitOptions?inputTextSplitOptions = null,
     bool skipFirstLine = false)
 {
     //
     indentSize
     .Arg(nameof(indentSize))
     .EnsureNotLessThanZero();
     //
     if (string.IsNullOrEmpty(inputText) || indent == string.Empty || indentSize < 1)
     {
         return(inputText);
     }
     lineSeparator         = lineSeparator ?? Environment.NewLine;
     indent                = indent ?? new string('\u0009', 1);
     inputTextSplitOptions = inputTextSplitOptions ?? StringSplitOptions.None;
     indentSize            = indentSize ?? 1;
     if (indentSize > 1)
     {
         if (indent.Length == 1)
         {
             indent = new string(c : indent[0], count : indentSize.Value);
         }
         else
         {
             using (var indentBuffer = EonStringBuilderUtilities.AcquireBuffer()) {
                 var indentBuilder = indentBuffer.StringBuilder;
                 for (var i = 0; i < indentSize; i++)
                 {
                     indentBuilder.Append(indent);
                 }
                 indent = indentBuilder.ToString();
             }
         }
     }
     //
     using (var outputBuffer = EonStringBuilderUtilities.AcquireBuffer()) {
         var outputBuilder = outputBuffer.StringBuilder;
         var lines         = inputText.Split(separator: new string[] { lineSeparator }, options: inputTextSplitOptions.Value);
         //
         if (lines.Length > 0)
         {
             if (!skipFirstLine)
             {
                 outputBuilder.Append(indent);
             }
             outputBuilder.Append(lines[0]);
             //
             for (var i = 1; i < lines.Length; i++)
             {
                 outputBuilder.Append(lineSeparator);
                 outputBuilder.Append(indent);
                 outputBuilder.Append(lines[i]);
             }
         }
         //
         return(outputBuilder.ToString());
     }
 }
コード例 #13
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);
            }
        }
コード例 #14
0
        public virtual bool TryInvolveHandler(IDependencyHandler2 handler, IDependencyHandler2 referrer = null)
        {
            handler.EnsureNotNull(nameof(handler));
            //
            var involvedExecutorsCounters = ReadDA(ref _involvedHandlerCounters);
            var involvedExecutorsChain    = ReadDA(ref _involvedHandlerChain);
            var spinLock = ReadDA(ref _involvedHandlerSpinLock);
            //
            var result = default(bool);
            var error  = default(Exception);

            try {
                result =
                    spinLock.Invoke(
                        () => {
                    EnsureNotDisposeState(considerDisposeRequest: true);
                    //
                    if (involvedExecutorsCounters.ContainsKey(handler))
                    {
                        if (involvedExecutorsCounters[handler] >= ExecutionsCountLimitPerExecutor)
                        {
                            return(false);
                        }
                        else
                        {
                            involvedExecutorsCounters[handler] += 1;
                        }
                    }
                    else
                    {
                        involvedExecutorsCounters.Add(handler, 1);
                    }
                    involvedExecutorsChain.Add(handler);
                    return(true);
                });
            }
            catch (Exception exception) {
                error = exception;
                throw;
            }
            finally {
                if (_isAdvancedLoggingEnabled)
                {
                    string contextDetailsText;
                    using (var acquiredBuffer = EonStringBuilderUtilities.AcquireBuffer()) {
                        var sb = acquiredBuffer.StringBuilder;
                        sb.AppendLine("Параметры разрешения функциональной зависимости:");
                        sb.AppendLine(Specs.ToString().IndentLines());
                        sb.AppendLine("Область функциональной зависимости:");
                        sb.AppendLine(Scope.ToString().IndentLines());
                        contextDetailsText = sb.ToString();
                    }
#if !DO_NOT_USE_EON_LOGGING_API
                    if (error is null)
                    {
                        this.IssueInformation(
                            $"Разрешение функциональной зависимости (ИД контекста '{_sequentialId:d}').",
                            $"Операция '{nameof(TryInvolveExecutor)}'.{Environment.NewLine}\tПараметры операции:{Environment.NewLine}\t\t{nameof(executor)}:{Environment.NewLine}{executor.ToString().IndentLines(indentSize: 3)}{Environment.NewLine}\t\t{nameof(referrer)}:{Environment.NewLine}{referrer.TextView().IndentLines(indentSize: 3)}{Environment.NewLine}\tКонтекст:{Environment.NewLine}{contextDetailsText.IndentLines(indentSize: 2)}{Environment.NewLine}\tРезультат: {result}");
                    }
                    else
                    {
                        try {
                            this.IssueError(
                                $"Разрешение функциональной зависимости (ИД контекста '{_sequentialId:d}').",
                                $"Операция '{nameof(TryInvolveExecutor)}'. Ошибка выполнения операции.{Environment.NewLine}\tПараметры операции:{Environment.NewLine}\t\t{nameof(executor)}:{Environment.NewLine}{executor.ToString().IndentLines(indentSize: 3)}{Environment.NewLine}\t\t{nameof(referrer)}:{Environment.NewLine}{referrer.TextView().IndentLines(indentSize: 3)}{Environment.NewLine}\tКонтекст:{Environment.NewLine}{contextDetailsText.IndentLines(indentSize: 2)}",
                                error,
                                severityLevel: SeverityLevel.High);
                        }
                        catch (Exception firstException) {
                            throw new AggregateException(error, firstException);
                        }
                    }
#endif
                }
            }
            //
            return(result);
        }