System.ArgumentOutOfRangeException 参数名称:System.Text.StringBuilder.ToString() 处的 chunkLength

System.ArgumentOutOfRangeException Parameter name: chunkLength at System.Text.StringBuilder.ToString()

我在日志文件中遇到以下异常。

System.ArgumentOutOfRangeException: Index was out of range. Must be non-negative and less than the size of the collection. Parameter name: chunkLength at System.Text.StringBuilder.ToString()

我相信这是因为 string Builder 不是线程安全的。但是我偶然发现了如何使我的字符串生成器在下面的递归函数中线程安全。

public static class StringExtensions
{
    /// <summary>
    /// The log key builder
    /// </summary>
    private static StringBuilder logKeyBuilder;

    public static string ConcatLogKeyWithExceptionMessage<T>(this T entity, string configuredLogKeys, bool logOnlySingleKey, string exceptionMessage, bool firstInvocation = true) where T : class
    {
        logKeyBuilder = logKeyBuilder ?? new StringBuilder();

        if (entity != null)
        {
            var objType = entity.GetType();
            var properties = objType.GetProperties();
            foreach (var property in properties)
            {
                var propValue = property.GetValue(entity, null);
                var elems = propValue as IList;
                if (elems != null)
                {
                    foreach (var item in elems)
                    {
                        {
                            ConcatLogKeyWithExceptionMessage(item, configuredLogKeys, logOnlySingleKey, exceptionMessage, false);
                        }
                    }
                }
                else
                {
                    // This will not cut-off System.Collections because of the first check
                    if (property.PropertyType.Assembly == objType.Assembly)
                    {
                        ConcatLogKeyWithExceptionMessage(propValue, configuredLogKeys, logOnlySingleKey, exceptionMessage, false);
                    }
                    else
                    {
                        configuredKeysArray = configuredKeysArray ?? (!string.IsNullOrEmpty(configuredLogKeys) ? configuredLogKeys.Split(',') : new string[0]);

                        foreach (var configLogKey in configuredKeysArray)
                        {
                            if (string.Compare(configLogKey.Trim(), property.Name.Trim(), StringComparison.OrdinalIgnoreCase) == 0)
                            {
                                configuredKeysArray = configuredKeysArray.Where(x => x != configLogKey).ToArray();
                                logKeyBuilder.Append(property.Name);
                                logKeyBuilder.Append(" ");
                                logKeyBuilder.Append("-");
                                logKeyBuilder.Append(" ");
                                logKeyBuilder.Append(property.GetValue(entity));
                                logKeyBuilder.Append(" ");
                                if (logOnlySingleKey)
                                {
                                    break;
                                }
                            }
                        }
                    }
                }
            }
        }

        logKeyBuilder = firstInvocation ? logKeyBuilder.Append(exceptionMessage) : logKeyBuilder;
        return logKeyBuilder.ToString();
    }
}

使用锁:

private static object lockObject = new object();
public static string ConcatLogKeyWithExceptionMessage<T>(this T entity, string configuredLogKeys, bool logOnlySingleKey, string exceptionMessage, bool firstInvocation = true) where T : class
{
    lock(lockObject )
    {
        // rest of your code here
    }
}

或者将您的静态字段移动为方法内的局部变量。