From 02132b7307ed7cc5fd4e144059ae782837ff6874 Mon Sep 17 00:00:00 2001 From: Michael Mortensen Date: Sat, 14 Sep 2024 00:56:42 +0200 Subject: [PATCH 01/37] :thread: change applied after looking in sourcecode for Start extension method for HostBuilder (https://github.com/dotnet/runtime/blob/main/src/libraries/Microsoft.Extensions.Hosting.Abstractions/src/HostingAbstractionsHostBuilderExtensions.cs) and this article: https://www.strathweb.com/2021/05/the-curious-case-of-asp-net-core-integration-test-deadlock/ --- .../AspNetCoreHostFixture.cs | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/Cuemon.Extensions.Xunit.Hosting.AspNetCore/AspNetCoreHostFixture.cs b/src/Cuemon.Extensions.Xunit.Hosting.AspNetCore/AspNetCoreHostFixture.cs index 2266a237..94963e56 100644 --- a/src/Cuemon.Extensions.Xunit.Hosting.AspNetCore/AspNetCoreHostFixture.cs +++ b/src/Cuemon.Extensions.Xunit.Hosting.AspNetCore/AspNetCoreHostFixture.cs @@ -1,5 +1,6 @@ using System; using System.IO; +using System.Threading.Tasks; using Cuemon.Collections.Generic; using Microsoft.AspNetCore.Builder; using Microsoft.AspNetCore.Hosting; @@ -88,7 +89,9 @@ public override void ConfigureHost(Test hostTest) o.ValidateScopes = true; }); - Host = hb.Start(); + var host = hb.Build(); + Task.Run(() => host.StartAsync()).GetAwaiter().GetResult(); + Host = host; } /// From c0d7b4ff44c45552720860191a9f9fa5fc3226c5 Mon Sep 17 00:00:00 2001 From: Michael Mortensen Date: Sat, 14 Sep 2024 15:48:13 +0200 Subject: [PATCH 02/37] :art: sqllitedb housekeeping --- .../Assets/SqliteDatabase.cs | 125 ++++++++++++++++++ .../Cuemon.Data.Tests.csproj | 2 +- test/Cuemon.Data.Tests/DataManagerTest.cs | 117 +--------------- 3 files changed, 127 insertions(+), 117 deletions(-) create mode 100644 test/Cuemon.Data.Tests/Assets/SqliteDatabase.cs diff --git a/test/Cuemon.Data.Tests/Assets/SqliteDatabase.cs b/test/Cuemon.Data.Tests/Assets/SqliteDatabase.cs new file mode 100644 index 00000000..93726e8d --- /dev/null +++ b/test/Cuemon.Data.Tests/Assets/SqliteDatabase.cs @@ -0,0 +1,125 @@ +using System; +using System.Globalization; +using System.IO; +using System.Linq; +using Cuemon.Reflection; +using Xunit.Abstractions; + +namespace Cuemon.Data.Assets +{ + internal static class SqliteDatabase + { + internal static void Create(DataManager manager, ITestOutputHelper output) + { + + manager.Execute(new DataStatement(""" + CREATE TABLE Product ( + ProductID INTEGER PRIMARY KEY, + Name TEXT NOT NULL, + ProductNumber TEXT NOT NULL, + MakeFlag INTEGER NOT NULL, + FinishedGoodsFlag INTEGER NOT NULL, + Color TEXT NULL, + SafetyStockLevel INTEGER NOT NULL, + ReorderPoint INTEGER NOT NULL, + StandardCost REAL NOT NULL, + ListPrice REAL NOT NULL, + Size TEXT NULL, + SizeUnitMeasureCode TEXT NULL, + WeightUnitMeasureCode TEXT NULL, + Weight REAL NULL, + DaysToManufacture INTEGER NOT NULL, + ProductLine TEXT NULL, + Class TEXT NULL, + Style TEXT NULL, + ProductSubcategoryID INTEGER NULL, + ProductModelID INTEGER NULL, + SellStartDate TEXT NOT NULL, + SellEndDate TEXT NULL, + DiscontinuedDate TEXT NULL, + RowGuid TEXT NOT NULL, + ModifiedDate TEXT NOT NULL); + """)); + + using var file = Decorator.Enclose(typeof(DsvDataReaderTest).Assembly).GetManifestResources("AdventureWorks2022_Product.csv", ManifestResourceMatch.ContainsName).Values.Single(); + using var reader = new DsvDataReader(new StreamReader(file), setup: o => + { + o.FormatProvider = CultureInfo.GetCultureInfo("da-DK"); + o.Delimiter = ";"; + }); + while (reader.Read()) + { + var statement = new DataStatement($$""" + INSERT INTO Product + ([ProductID] + ,[Name] + ,[ProductNumber] + ,[MakeFlag] + ,[FinishedGoodsFlag] + ,[Color] + ,[SafetyStockLevel] + ,[ReorderPoint] + ,[StandardCost] + ,[ListPrice] + ,[Size] + ,[SizeUnitMeasureCode] + ,[WeightUnitMeasureCode] + ,[Weight] + ,[DaysToManufacture] + ,[ProductLine] + ,[Class] + ,[Style] + ,[ProductSubcategoryID] + ,[ProductModelID] + ,[SellStartDate] + ,[SellEndDate] + ,[DiscontinuedDate] + ,[RowGuid] + ,[ModifiedDate]) + VALUES + ({{reader.GetInt32(0)}}, + "{{reader.GetString(1)}}", + "{{reader.GetString(2)}}", + {{reader.GetInt32(3)}}, + {{reader.GetInt32(4)}}, + {{StringOrNull(reader.GetString(5))}}, + {{reader.GetInt32(6)}}, + {{reader.GetInt32(7)}}, + {{reader.GetDecimal(8).ToString("F", CultureInfo.InvariantCulture)}}, + {{reader.GetDecimal(9).ToString("F", CultureInfo.InvariantCulture)}}, + {{StringOrNull(reader.GetString(10))}}, + {{StringOrNull(reader.GetString(11))}}, + {{StringOrNull(reader.GetString(12))}}, + {{(reader.GetString(13) == "NULL" ? "NULL" : reader.GetDecimal(13).ToString("F", CultureInfo.InvariantCulture))}}, + {{reader.GetInt32(14)}}, + {{StringOrNull(reader.GetString(15))}}, + {{StringOrNull(reader.GetString(16))}}, + {{StringOrNull(reader.GetString(17))}}, + {{(reader.GetString(18) == "NULL" ? "NULL" : reader.GetInt32(18))}}, + {{(reader.GetString(19) == "NULL" ? "NULL" : reader.GetInt32(19))}}, + "{{reader.GetDateTime(20):O}}", + {{(reader.GetString(21) == "NULL" ? "NULL" : string.Concat("\"", reader.GetDateTime(21).ToString("O"), "\""))}}, + {{(reader.GetString(22) == "NULL" ? "NULL" : string.Concat("\"", reader.GetDateTime(22).ToString("O"), "\""))}}, + "{{reader.GetString(23)}}", + "{{reader.GetDateTime(24):O}}") + """); + + try + { + manager.Execute(statement); + } + catch (Exception e) + { + output.WriteLine(statement.Text); + throw; + } + } + } + + private static string StringOrNull(string value) + { + if (value == "NULL") { return "NULL"; } + return (value.StartsWith("\"") && value.EndsWith("\"")) ? $"{value}" : $"\"{value}\""; + } + } +} diff --git a/test/Cuemon.Data.Tests/Cuemon.Data.Tests.csproj b/test/Cuemon.Data.Tests/Cuemon.Data.Tests.csproj index 46c6044e..bbb90760 100644 --- a/test/Cuemon.Data.Tests/Cuemon.Data.Tests.csproj +++ b/test/Cuemon.Data.Tests/Cuemon.Data.Tests.csproj @@ -44,7 +44,7 @@ - + diff --git a/test/Cuemon.Data.Tests/DataManagerTest.cs b/test/Cuemon.Data.Tests/DataManagerTest.cs index 005d4900..5f4835c4 100644 --- a/test/Cuemon.Data.Tests/DataManagerTest.cs +++ b/test/Cuemon.Data.Tests/DataManagerTest.cs @@ -1,6 +1,4 @@ using System; -using System.Globalization; -using System.IO; using System.Linq; using System.Threading.Tasks; using Cuemon.Collections.Generic; @@ -8,7 +6,6 @@ using Cuemon.Extensions; using Cuemon.Extensions.Data; using Cuemon.Extensions.Xunit.Hosting; -using Cuemon.Reflection; using Cuemon.Resilience; using Microsoft.Data.Sqlite; using Microsoft.Extensions.DependencyInjection; @@ -393,121 +390,9 @@ public override void ConfigureServices(IServiceCollection services) o.LeaveCommandOpen = true; // do not release our command as it will trigger errors from data readers (for normal dbs - always leave false) o.ConnectionString = "Data Source=InMemory;Mode=Memory;Cache=Shared"; }); - InitSqliteDatabase(manager); + SqliteDatabase.Create(manager, TestOutput); services.AddSingleton(manager); } - private void InitSqliteDatabase(DataManager manager) - { - - manager.Execute(new DataStatement(""" - CREATE TABLE Product ( - ProductID INTEGER PRIMARY KEY, - Name TEXT NOT NULL, - ProductNumber TEXT NOT NULL, - MakeFlag INTEGER NOT NULL, - FinishedGoodsFlag INTEGER NOT NULL, - Color TEXT NULL, - SafetyStockLevel INTEGER NOT NULL, - ReorderPoint INTEGER NOT NULL, - StandardCost REAL NOT NULL, - ListPrice REAL NOT NULL, - Size TEXT NULL, - SizeUnitMeasureCode TEXT NULL, - WeightUnitMeasureCode TEXT NULL, - Weight REAL NULL, - DaysToManufacture INTEGER NOT NULL, - ProductLine TEXT NULL, - Class TEXT NULL, - Style TEXT NULL, - ProductSubcategoryID INTEGER NULL, - ProductModelID INTEGER NULL, - SellStartDate TEXT NOT NULL, - SellEndDate TEXT NULL, - DiscontinuedDate TEXT NULL, - RowGuid TEXT NOT NULL, - ModifiedDate TEXT NOT NULL); - """)); - - using var file = Decorator.Enclose(typeof(DsvDataReaderTest).Assembly).GetManifestResources("AdventureWorks2022_Product.csv", ManifestResourceMatch.ContainsName).Values.Single(); - using var reader = new DsvDataReader(new StreamReader(file), setup: o => - { - o.FormatProvider = CultureInfo.GetCultureInfo("da-DK"); - o.Delimiter = ";"; - }); - while (reader.Read()) - { - var statement = new DataStatement($$""" - INSERT INTO Product - ([ProductID] - ,[Name] - ,[ProductNumber] - ,[MakeFlag] - ,[FinishedGoodsFlag] - ,[Color] - ,[SafetyStockLevel] - ,[ReorderPoint] - ,[StandardCost] - ,[ListPrice] - ,[Size] - ,[SizeUnitMeasureCode] - ,[WeightUnitMeasureCode] - ,[Weight] - ,[DaysToManufacture] - ,[ProductLine] - ,[Class] - ,[Style] - ,[ProductSubcategoryID] - ,[ProductModelID] - ,[SellStartDate] - ,[SellEndDate] - ,[DiscontinuedDate] - ,[RowGuid] - ,[ModifiedDate]) - VALUES - ({{reader.GetInt32(0)}}, - "{{reader.GetString(1)}}", - "{{reader.GetString(2)}}", - {{reader.GetInt32(3)}}, - {{reader.GetInt32(4)}}, - {{StringOrNull(reader.GetString(5))}}, - {{reader.GetInt32(6)}}, - {{reader.GetInt32(7)}}, - {{reader.GetDecimal(8).ToString("F", CultureInfo.InvariantCulture)}}, - {{reader.GetDecimal(9).ToString("F", CultureInfo.InvariantCulture)}}, - {{StringOrNull(reader.GetString(10))}}, - {{StringOrNull(reader.GetString(11))}}, - {{StringOrNull(reader.GetString(12))}}, - {{(reader.GetString(13) == "NULL" ? "NULL" : reader.GetDecimal(13).ToString("F", CultureInfo.InvariantCulture))}}, - {{reader.GetInt32(14)}}, - {{StringOrNull(reader.GetString(15))}}, - {{StringOrNull(reader.GetString(16))}}, - {{StringOrNull(reader.GetString(17))}}, - {{(reader.GetString(18) == "NULL" ? "NULL" : reader.GetInt32(18))}}, - {{(reader.GetString(19) == "NULL" ? "NULL" : reader.GetInt32(19))}}, - "{{reader.GetDateTime(20):O}}", - {{(reader.GetString(21) == "NULL" ? "NULL" : string.Concat("\"", reader.GetDateTime(21).ToString("O"), "\""))}}, - {{(reader.GetString(22) == "NULL" ? "NULL" : string.Concat("\"", reader.GetDateTime(22).ToString("O"), "\""))}}, - "{{reader.GetString(23)}}", - "{{reader.GetDateTime(24):O}}") - """); - - try - { - manager.Execute(statement); - } - catch (Exception e) - { - TestOutput.WriteLine(statement.Text); - throw; - } - } - } - - private static string StringOrNull(string value) - { - if (value == "NULL") { return "NULL"; } - return (value.StartsWith("\"") && value.EndsWith("\"")) ? $"{value}" : $"\"{value}\""; - } } } From b4619b342f58df0785fef498763535cce125f1df Mon Sep 17 00:00:00 2001 From: Michael Mortensen Date: Sat, 14 Sep 2024 15:49:04 +0200 Subject: [PATCH 03/37] :boom: removed BulkCopyDataReader --- src/Cuemon.Data/BulkCopyDataReader.cs | 500 -------------------------- 1 file changed, 500 deletions(-) delete mode 100644 src/Cuemon.Data/BulkCopyDataReader.cs diff --git a/src/Cuemon.Data/BulkCopyDataReader.cs b/src/Cuemon.Data/BulkCopyDataReader.cs deleted file mode 100644 index c3fb3225..00000000 --- a/src/Cuemon.Data/BulkCopyDataReader.cs +++ /dev/null @@ -1,500 +0,0 @@ -using System; -using System.Collections; -using System.Collections.Generic; -using System.Collections.Specialized; -using System.Data.Common; -using System.Globalization; -using System.Linq; -using System.Text; - -namespace Cuemon.Data -{ - /// - /// Provides a way of copying an existing object implementing the class to a filtered forward-only stream of rows that is mapped for bulk upload. This class cannot be inherited. - /// - public sealed class BulkCopyDataReader : DbDataReader - { - private static readonly object PadLock = new(); - private IOrderedDictionary _defaultFields; - - /// - /// Initializes a new instance of the class. - /// - /// The object that contains the data. - /// A sequence of elements that specifies the data to be copied. - public BulkCopyDataReader(DbDataReader reader, IEnumerable mappings) - { - Validator.ThrowIfNull(reader); - Validator.ThrowIfNull(mappings); - - Reader = reader; - Fields = new OrderedDictionary(StringComparer.OrdinalIgnoreCase); - Mappings = new List(mappings); - Init(); - } - - private void Init() - { - foreach (var mapping in Mappings.Select(mapping => mapping.Source)) - { - if (string.IsNullOrEmpty(mapping)) { continue; } - Fields.Add(mapping, null); - } - if (Fields.Count > 0 && - Fields.Count != Mappings.Count) { throw new InvalidOperationException("Mappings must be either all name or all ordinal based."); } - UseOrdinal = Fields.Count == 0; - } - - private DbDataReader Reader { get; set; } - - private void SetFields(IOrderedDictionary fields) - { - Fields = fields; - } - - private bool UseOrdinal { get; set; } - - /// - /// Gets the sequence of elements that specifies the data to be copied. - /// - /// The elements that specifies the data to be copied. - public IList Mappings { get; private set; } - - #region Properties - /// - /// Gets the column with the specified name. - /// - /// The name of the column to find. - /// The column with the specified name as an . - public override object this[string name] => Fields[name]; - - /// - /// Gets the column located at the specified index. - /// - /// The zero-based index of the column to get. - /// The column located at the specified index as an . - public override object this[int i] => Fields[i]; - - /// - /// Gets the number of rows changed, inserted, or deleted by execution of the SQL statement. - /// - /// The records affected. - public override int RecordsAffected => -1; - - private IOrderedDictionary Fields { get; set; } - - /// - /// Gets a value that indicates whether this contains one or more rows. - /// - /// true if this instance has rows; otherwise, false. - public override bool HasRows => Reader.HasRows; - - /// - /// Gets a value indicating whether the data reader is closed. - /// - /// true if this instance is closed; otherwise, false. - public override bool IsClosed => IsDisposed; - - private bool IsDisposed { get; set; } - - /// - /// Gets the currently processed row count of this instance. - /// - /// The currently processed row count of this instance. - /// This property is incremented when the invoked method returns true. - public int RowCount { get; private set; } - - /// - /// Gets the number of columns in the current row. - /// - /// When not positioned in a valid recordset, 0; otherwise, the number of columns in the current record. - public override int FieldCount => Mappings.Count; - - #endregion - - #region Methods - private IOrderedDictionary GetDefault() - { - if (_defaultFields == null) - { - lock (PadLock) - { - if (_defaultFields == null) - { - _defaultFields = new OrderedDictionary(); - if (UseOrdinal) - { - foreach (var mapping in Mappings.Where(mapping => mapping is IndexMapping).Cast()) - { - _defaultFields.Add(mapping.SourceIndex, null); - } - } - else - { - foreach (var mapping in Mappings) - { - _defaultFields.Add(mapping.Source, null); - } - } - } - } - } - return Reset(_defaultFields); - } - - private IOrderedDictionary Reset(IOrderedDictionary source) - { - var result = UseOrdinal ? new OrderedDictionary(source.Count, EqualityComparer.Default) : new OrderedDictionary(source.Count, StringComparer.OrdinalIgnoreCase); - foreach (DictionaryEntry o in source) - { - result.Add(o.Key, o.Value); - } - return result; - } - - /// - /// Advances the to the next record. - /// - /// true if there are more rows; otherwise, false. - public override bool Read() - { - if (!Reader.Read()) { return false; } - var fields = GetDefault(); - for (var i = 0; i < Reader.FieldCount; i++) - { - if (UseOrdinal) - { - if (fields.Contains(i)) - { - fields[i] = Reader[i]; - } - } - else - { - if (IsMatch(Reader.GetName(i)) && fields.Contains(Reader.GetName(i))) - { - fields[Reader.GetName(i)] = Reader[Reader.GetName(i)]; - } - } - } - RowCount++; - SetFields(fields); - return true; - } - - private bool IsMatch(string localName) - { - foreach (var mapping in Mappings) - { - if (mapping.Source.Equals(localName, StringComparison.OrdinalIgnoreCase)) { return true; } - } - return false; - } - - /// - /// Gets the value of the specified column as a Boolean. - /// - /// The zero-based column ordinal. - /// The value of the column. - public override bool GetBoolean(int ordinal) - { - return Convert.ToBoolean(GetValue(ordinal), CultureInfo.InvariantCulture); - } - - /// - /// Gets the 8-bit unsigned integer value of the specified column. - /// - /// The zero-based column ordinal. - /// The 8-bit unsigned integer value of the specified column. - public override byte GetByte(int ordinal) - { - return Convert.ToByte(GetValue(ordinal), CultureInfo.InvariantCulture); - } - - /// - /// Reads a stream of bytes from the specified column, starting at location indicated by dataOffset, into the buffer, starting at the location indicated by bufferOffset. - /// - /// The zero-based column ordinal. - /// The index within the row from which to begin the read operation. - /// The buffer into which to copy the data. - /// The index with the buffer to which the data will be copied. - /// The maximum number of characters to read. - /// The actual number of bytes read. - public override long GetBytes(int ordinal, long dataOffset, byte[] buffer, int bufferOffset, int length) - { - return 0; - } - - /// - /// Gets the character value of the specified column. - /// - /// The zero-based column ordinal. - /// The character value of the specified column. - public override char GetChar(int ordinal) - { - return Convert.ToChar(GetValue(ordinal), CultureInfo.InvariantCulture); - } - - /// - /// Gets the date and time data value of the specified field. - /// - /// The index of the field to find. - /// The date and time data value of the specified field. - public override DateTime GetDateTime(int ordinal) - { - return (DateTime)GetValue(ordinal); - } - - /// - /// Gets the fixed-position numeric value of the specified field. - /// - /// The index of the field to find. - /// The fixed-position numeric value of the specified field. - public override decimal GetDecimal(int ordinal) - { - return Convert.ToDecimal(GetValue(ordinal), CultureInfo.InvariantCulture); - } - - /// - /// Gets the double-precision floating point number of the specified field. - /// - /// The index of the field to find. - /// The double-precision floating point number of the specified field. - public override double GetDouble(int ordinal) - { - return Convert.ToDouble(GetValue(ordinal), CultureInfo.InvariantCulture); - } - - /// - /// Returns an that can be used to iterate through the rows in the data reader. - /// - /// An that can be used to iterate through the rows in the data reader. - /// - public override IEnumerator GetEnumerator() - { - throw new NotImplementedException(); - } - - /// - /// Gets the information corresponding to the type of that would be returned from . - /// - /// The index of the field to find. - /// The information corresponding to the type of that would be returned from . - public override Type GetFieldType(int ordinal) - { - return GetValue(ordinal).GetType(); - } - - /// - /// Gets the single-precision floating point number of the specified field. - /// - /// The index of the field to find. - /// The single-precision floating point number of the specified field. - public override float GetFloat(int ordinal) - { - return Convert.ToSingle(GetValue(ordinal), CultureInfo.InvariantCulture); - } - - /// - /// Returns the GUID value of the specified field. - /// - /// The index of the field to find. - /// The GUID value of the specified field. - public override Guid GetGuid(int ordinal) - { - return (Guid)GetValue(ordinal); - } - - /// - /// Gets the 16-bit signed integer value of the specified field. - /// - /// The index of the field to find. - /// The 16-bit signed integer value of the specified field. - public override short GetInt16(int ordinal) - { - return Convert.ToInt16(GetValue(ordinal), CultureInfo.InvariantCulture); - } - - /// - /// Gets the 32-bit signed integer value of the specified field. - /// - /// The index of the field to find. - /// The 32-bit signed integer value of the specified field. - public override int GetInt32(int ordinal) - { - return Convert.ToInt32(GetValue(ordinal), CultureInfo.InvariantCulture); - } - - /// - /// Gets the 64-bit signed integer value of the specified field. - /// - /// The index of the field to find. - /// The 64-bit signed integer value of the specified field. - public override long GetInt64(int ordinal) - { - return Convert.ToInt64(GetValue(ordinal), CultureInfo.InvariantCulture); - } - - /// - /// Gets the name for the field to find. - /// - /// The index of the field to find. - /// The name of the field or the empty string (""), if there is no value to return. - public override string GetName(int ordinal) - { - var current = 0; - foreach (var mapping in Mappings) - { - if (ordinal == current) { return mapping.Source; } - current++; - } - return string.Empty; - } - - /// - /// Return the index of the named field. - /// - /// The name of the field to find. - /// The index of the named field. - /// - /// is null. - /// - /// - /// is not a valid column name. - /// - public override int GetOrdinal(string name) - { - Validator.ThrowIfNull(name); - var current = 0; - foreach (var mapping in Mappings) - { - if (mapping.Source.Equals(name, StringComparison.OrdinalIgnoreCase)) { return current; } - current++; - } - throw new ArgumentOutOfRangeException(nameof(name), "The name specified name is not a valid column name."); - } - - /// - /// Gets the string value of the specified field. - /// - /// The index of the field to find. - /// The string value of the specified field. - public override string GetString(int ordinal) - { - return GetValue(ordinal) as string; - } - - /// - /// Return the value of the specified field. - /// - /// The index of the field to find. - /// The which will contain the field value upon return. - public override object GetValue(int ordinal) - { - return Fields[ordinal]; - } - - /// - /// Return whether the specified field is set to null. - /// - /// The index of the field to find. - /// true if the specified field is set to null; otherwise, false. - public override bool IsDBNull(int ordinal) - { - return GetValue(ordinal) == null || GetValue(ordinal) == DBNull.Value; - } - - /// - /// Releases the managed resources used by the and optionally releases the unmanaged resources. - /// - /// true to release managed and unmanaged resources; false to release only unmanaged resources. - protected override void Dispose(bool disposing) - { - if (IsDisposed) { return; } - base.Dispose(disposing); - try - { - if (disposing) - { - Reader.Dispose(); - } - } - finally - { - IsDisposed = true; - } - } - - /// - /// Gets a value indicating the depth of nesting for the current row. - /// - /// The depth of nesting for the current row. - /// The outermost table has a depth of zero. - public override int Depth => 0; - - /// - /// Populates an array of objects with the column values of the current record. - /// - /// An array of to copy the attribute fields into. - /// The number of instances of in the array. - public override int GetValues(object[] values) - { - Validator.ThrowIfNull(values); - var length = FieldCount; - for (var i = 0; i < length; i++) - { - values[i] = GetValue(i); - } - return length; - } - - /// - /// Advances the reader to the next result when reading the results of a batch of statements. - /// - /// true if there are more result sets; otherwise false. - public override bool NextResult() - { - return false; - } - - /// - /// Reads a stream of characters from the specified column, starting at location indicated by dataOffset, into the buffer, starting at the location indicated by bufferOffset. - /// - /// The zero-based column ordinal. - /// The index within the row from which to begin the read operation. - /// The buffer into which to copy the data. - /// The index with the buffer to which the data will be copied. - /// The maximum number of characters to read. - /// The actual number of characters read. - public override long GetChars(int ordinal, long dataOffset, char[] buffer, int bufferOffset, int length) - { - return 0; - } - - /// - /// Gets the name of the data type. - /// - /// The zero-based column ordinal. - /// System.String. - public override string GetDataTypeName(int ordinal) - { - return typeof(string).ToString(); - } - - /// - /// Returns a that represents the current row of this instance. - /// - /// A that represents the current row of this instance. - public override string ToString() - { - var builder = new StringBuilder(); - for (var i = 0; i < FieldCount; i++) - { - builder.AppendFormat("{0}={1}, ", GetName(i), GetValue(i)); - } - if (builder.Length > 0) { builder.Remove(builder.Length - 2, 2); } - return builder.ToString(); - } - #endregion - } -} \ No newline at end of file From 20ad8616a5bbfe64c911e8ed2a361ce56433de99 Mon Sep 17 00:00:00 2001 From: Michael Mortensen Date: Sat, 14 Sep 2024 15:58:41 +0200 Subject: [PATCH 04/37] :rotating_light: https://learn.microsoft.com/en-us/dotnet/fundamentals/code-analysis/quality-rules/ca1010 --- src/Cuemon.Net/QueryStringCollection.cs | 22 +++++++++++++++++-- .../QueryStringCollectionTest.cs | 2 +- 2 files changed, 21 insertions(+), 3 deletions(-) diff --git a/src/Cuemon.Net/QueryStringCollection.cs b/src/Cuemon.Net/QueryStringCollection.cs index 46952d0a..a1d116be 100644 --- a/src/Cuemon.Net/QueryStringCollection.cs +++ b/src/Cuemon.Net/QueryStringCollection.cs @@ -1,5 +1,8 @@ using System; +using System.Collections; +using System.Collections.Generic; using System.Collections.Specialized; +using System.Linq; using Cuemon.Net.Collections.Specialized; namespace Cuemon.Net @@ -9,7 +12,7 @@ namespace Cuemon.Net /// Implements the /// /// - public class QueryStringCollection : NameValueCollection + public class QueryStringCollection : NameValueCollection, IReadOnlyCollection> { /// /// Initializes a new instance of the class. @@ -36,6 +39,21 @@ public QueryStringCollection(string query, bool urlDecode = false) Add(Decorator.Enclose(query, false).ToQueryString(urlDecode)); } + IEnumerator IEnumerable.GetEnumerator() + { + return GetEnumerator(); + } + + /// + /// Returns an enumerator that iterates through the collection. + /// + /// An enumerator that can be used to iterate through the collection. + + public new IEnumerator> GetEnumerator() + { + return base.AllKeys.Select(key => new KeyValuePair(key, base[key])).GetEnumerator(); + } + /// /// Returns a that represents this instance. /// @@ -45,4 +63,4 @@ public override string ToString() return Decorator.Enclose(this).ToString(FieldValueSeparator.Ampersand, false); } } -} \ No newline at end of file +} diff --git a/test/Cuemon.Net.Tests/QueryStringCollectionTest.cs b/test/Cuemon.Net.Tests/QueryStringCollectionTest.cs index d18272bf..2869813c 100644 --- a/test/Cuemon.Net.Tests/QueryStringCollectionTest.cs +++ b/test/Cuemon.Net.Tests/QueryStringCollectionTest.cs @@ -26,4 +26,4 @@ public void Class_ShouldHaveKeysAndValuesRulesetAsQueryString() } } -} \ No newline at end of file +} From 7db0558cb1112bfedd665d295a07befcdfbb8d10 Mon Sep 17 00:00:00 2001 From: Michael Mortensen Date: Sat, 14 Sep 2024 16:20:09 +0200 Subject: [PATCH 05/37] :boom: removed NewLine constant from Alphanumeric as it could cause confusion with Environment.NewLine --- .../AuthorizationHeaderBuilder.cs | 4 ++-- src/Cuemon.Core/Alphanumeric.cs | 7 +------ src/Cuemon.Core/Diagnostics/ExceptionDescriptor.cs | 4 ++-- src/Cuemon.Core/ExceptionInsights.cs | 8 ++++---- src/Cuemon.Core/GlobalSuppressions.cs | 1 + test/Cuemon.Core.Tests/DayPartTest.cs | 4 ++-- 6 files changed, 12 insertions(+), 16 deletions(-) diff --git a/src/Cuemon.AspNetCore.Authentication/AuthorizationHeaderBuilder.cs b/src/Cuemon.AspNetCore.Authentication/AuthorizationHeaderBuilder.cs index df8aa5d8..81096149 100644 --- a/src/Cuemon.AspNetCore.Authentication/AuthorizationHeaderBuilder.cs +++ b/src/Cuemon.AspNetCore.Authentication/AuthorizationHeaderBuilder.cs @@ -121,7 +121,7 @@ public ImmutableDictionary ToImmutableDictionary() /// A that represents this instance. public override string ToString() { - return DelimitedString.Create(Data.Keys.Select(key => $"{key}={Data[key]}"), o => o.Delimiter = Alphanumeric.NewLine + Alphanumeric.NewLine); + return DelimitedString.Create(Data.Keys.Select(key => $"{key}={Data[key]}"), o => o.Delimiter = Environment.NewLine + Environment.NewLine); } } -} \ No newline at end of file +} diff --git a/src/Cuemon.Core/Alphanumeric.cs b/src/Cuemon.Core/Alphanumeric.cs index 3611fdff..e6634658 100644 --- a/src/Cuemon.Core/Alphanumeric.cs +++ b/src/Cuemon.Core/Alphanumeric.cs @@ -46,15 +46,10 @@ public static class Alphanumeric public const string Hexadecimal = Numbers + "ABCDEF"; /// - /// A network-path reference, eg. two forward slashes (//). + /// A network-path reference, e.g. two forward slashes (//). /// public const string NetworkPathReference = "//"; - /// - /// Carriage-return/linefeed character combination. - /// - public const string NewLine = CarriageReturn + Linefeed; - /// /// Tab character. /// diff --git a/src/Cuemon.Core/Diagnostics/ExceptionDescriptor.cs b/src/Cuemon.Core/Diagnostics/ExceptionDescriptor.cs index 24c194aa..a111f402 100644 --- a/src/Cuemon.Core/Diagnostics/ExceptionDescriptor.cs +++ b/src/Cuemon.Core/Diagnostics/ExceptionDescriptor.cs @@ -41,7 +41,7 @@ public static ExceptionDescriptor Extract(Exception exception, string code = "Un { var memberSignature = Convertible.ToString(Convert.FromBase64String(insights[IndexOfThrower])); var runtimeParameters = Convertible.ToString(Convert.FromBase64String(insights[IndexOfRuntimeParameters])); - ed.AddEvidence("Thrower", new MemberEvidence(memberSignature, string.IsNullOrWhiteSpace(runtimeParameters) ? null : runtimeParameters.Split(Alphanumeric.NewLine.ToCharArray(), StringSplitOptions.RemoveEmptyEntries).ToDictionary(k => k.Substring(0, k.IndexOf('=')), v => + ed.AddEvidence("Thrower", new MemberEvidence(memberSignature, string.IsNullOrWhiteSpace(runtimeParameters) ? null : runtimeParameters.Split(Environment.NewLine.ToCharArray(), StringSplitOptions.RemoveEmptyEntries).ToDictionary(k => k.Substring(0, k.IndexOf('=')), v => { var t = v.Substring(v.IndexOf('=') + 1); if (t == "null") { return null; } @@ -78,7 +78,7 @@ private static void TryAddEvidence(ExceptionDescriptor ed, string context, strin var info = Convertible.ToString(Convert.FromBase64String(base64)); if (!string.IsNullOrWhiteSpace(info)) { - ed.AddEvidence(context, info.Split(Alphanumeric.NewLine.ToCharArray(), StringSplitOptions.RemoveEmptyEntries), s => s.ToDictionary(k => k.Substring(0, k.IndexOf(':')), v => + ed.AddEvidence(context, info.Split(Environment.NewLine.ToCharArray(), StringSplitOptions.RemoveEmptyEntries), s => s.ToDictionary(k => k.Substring(0, k.IndexOf(':')), v => { var presult = v.Substring(v.IndexOf(' ') + 1); return ParserFactory.FromValueType().Parse(presult == "null" ? null : presult); diff --git a/src/Cuemon.Core/ExceptionInsights.cs b/src/Cuemon.Core/ExceptionInsights.cs index d0e8b9b0..90d3570a 100644 --- a/src/Cuemon.Core/ExceptionInsights.cs +++ b/src/Cuemon.Core/ExceptionInsights.cs @@ -58,7 +58,7 @@ public static T Embed(T exception, MethodBase thrower, object[] runtimeParame var rp = DelimitedString.Create(MethodDescriptor.MergeParameters(descriptor, runtimeParameters), o => { o.StringConverter = pair => FormattableString.Invariant($"{pair.Key}={pair.Value ?? "null"}"); - o.Delimiter = FormattableString.Invariant($"{Alphanumeric.NewLine}"); + o.Delimiter = FormattableString.Invariant($"{Environment.NewLine}"); }); builder.Append(Convert.ToBase64String(Convertible.GetBytes(FormattableString.Invariant($"{rp}")))); } @@ -83,7 +83,7 @@ private static void EmbedSystemSnapshot(StringBuilder builder, SystemSnapshots s builder.Append('.'); if (snapshots.HasFlag(SystemSnapshots.CaptureThreadInfo)) { - var ti = string.Join(Alphanumeric.NewLine, new ThreadInfo(Thread.CurrentThread).ToString().Split(Alphanumeric.CaretChar)); + var ti = string.Join(Environment.NewLine, new ThreadInfo(Thread.CurrentThread).ToString().Split(Alphanumeric.CaretChar)); builder.Append(ti.Length > 0 ? Convert.ToBase64String(Convertible.GetBytes(FormattableString.Invariant($"{ti}"))) : empty); } else @@ -93,7 +93,7 @@ private static void EmbedSystemSnapshot(StringBuilder builder, SystemSnapshots s builder.Append('.'); if (snapshots.HasFlag(SystemSnapshots.CaptureProcessInfo)) { - var pi = string.Join(Alphanumeric.NewLine, new ProcessInfo(Process.GetCurrentProcess()).ToString().Split(Alphanumeric.CaretChar)); + var pi = string.Join(Environment.NewLine, new ProcessInfo(Process.GetCurrentProcess()).ToString().Split(Alphanumeric.CaretChar)); builder.Append(pi.Length > 0 ? Convert.ToBase64String(Convertible.GetBytes(FormattableString.Invariant($"{pi}"))) : empty); } else @@ -103,7 +103,7 @@ private static void EmbedSystemSnapshot(StringBuilder builder, SystemSnapshots s builder.Append('.'); if (snapshots.HasFlag(SystemSnapshots.CaptureEnvironmentInfo)) { - var ei = string.Join(Alphanumeric.NewLine, new EnvironmentInfo().ToString().Split(Alphanumeric.CaretChar)); + var ei = string.Join(Environment.NewLine, new EnvironmentInfo().ToString().Split(Alphanumeric.CaretChar)); builder.Append(ei.Length > 0 ? Convert.ToBase64String(Convertible.GetBytes(FormattableString.Invariant($"{ei}"))) : empty); } else diff --git a/src/Cuemon.Core/GlobalSuppressions.cs b/src/Cuemon.Core/GlobalSuppressions.cs index d07f6a69..93f956fe 100644 --- a/src/Cuemon.Core/GlobalSuppressions.cs +++ b/src/Cuemon.Core/GlobalSuppressions.cs @@ -259,3 +259,4 @@ [assembly: SuppressMessage("Design", "CA1000:Do not declare static members on generic types", Justification = "By design; supports consistent developer experience for all formatters, e.g., SerializeObject/DeserializeObject.", Scope = "member", Target = "~M:Cuemon.Runtime.Serialization.Formatters.StreamFormatter`1.SerializeObject(System.Object,System.Type)~System.IO.Stream")] [assembly: SuppressMessage("Design", "CA1000:Do not declare static members on generic types", Justification = "By design; supports consistent developer experience for all formatters, e.g., SerializeObject/DeserializeObject.", Scope = "member", Target = "~M:Cuemon.Runtime.Serialization.Formatters.StreamFormatter`1.SerializeObject(System.Object,System.Type,`0)~System.IO.Stream")] [assembly: SuppressMessage("Design", "CA1000:Do not declare static members on generic types", Justification = "By design; supports consistent developer experience for all formatters, e.g., SerializeObject/DeserializeObject.", Scope = "member", Target = "~M:Cuemon.Runtime.Serialization.Formatters.StreamFormatter`1.SerializeObject(System.Object,System.Type,System.Action{`0})~System.IO.Stream")] +[assembly: SuppressMessage("Globalization", "CA1304:Specify CultureInfo", Justification = "False-Positive. Overload exists.", Scope = "member", Target = "~M:Cuemon.DateSpan.Parse(System.String)~Cuemon.DateSpan")] diff --git a/test/Cuemon.Core.Tests/DayPartTest.cs b/test/Cuemon.Core.Tests/DayPartTest.cs index 6a4dc7bc..8dac4f2f 100644 --- a/test/Cuemon.Core.Tests/DayPartTest.cs +++ b/test/Cuemon.Core.Tests/DayPartTest.cs @@ -101,9 +101,9 @@ public void Ctor_ShouldListAndVerifyAllBuiltInDayParts() part => Assert.Equal(part.Name, nameof(DayPart.Evening)) ); - var all = DelimitedString.Create(sut.Select(part => part.ToString()), o => o.Delimiter = Alphanumeric.NewLine); + var all = DelimitedString.Create(sut.Select(part => part.ToString()), o => o.Delimiter = Environment.NewLine); TestOutput.WriteLine(all); } } -} \ No newline at end of file +} From 86e3a398194faa3bbe6c82242536d7e957e10cdb Mon Sep 17 00:00:00 2001 From: Michael Mortensen Date: Sat, 14 Sep 2024 16:27:52 +0200 Subject: [PATCH 06/37] :rotating_light: https://learn.microsoft.com/en-us/dotnet/fundamentals/code-analysis/quality-rules/ca1304 --- src/Cuemon.AspNetCore/GlobalSuppressions.cs | 1 + src/Cuemon.Core/GlobalSuppressions.cs | 2 ++ src/Cuemon.Extensions.AspNetCore/GlobalSuppressions.cs | 1 + 3 files changed, 4 insertions(+) diff --git a/src/Cuemon.AspNetCore/GlobalSuppressions.cs b/src/Cuemon.AspNetCore/GlobalSuppressions.cs index 93ad6d83..c03c8e0c 100644 --- a/src/Cuemon.AspNetCore/GlobalSuppressions.cs +++ b/src/Cuemon.AspNetCore/GlobalSuppressions.cs @@ -19,3 +19,4 @@ [assembly: SuppressMessage("Style", "IDE0130:Namespace does not match folder structure", Justification = "Intentional as these embark on IDecorator.", Scope = "namespace", Target = "~N:Cuemon.AspNetCore.Diagnostics")] [assembly: SuppressMessage("Style", "IDE0130:Namespace does not match folder structure", Justification = "Intentional as these embark on IDecorator.", Scope = "namespace", Target = "~N:Cuemon.AspNetCore.Http")] [assembly: SuppressMessage("Style", "IDE0130:Namespace does not match folder structure", Justification = "Intentional as these embark on IDecorator.", Scope = "namespace", Target = "~N:Cuemon.AspNetCore.Http.Headers")] +[assembly: SuppressMessage("Globalization", "CA1304:Specify CultureInfo", Justification = "Not relevant in this context.", Scope = "member", Target = "~P:Cuemon.AspNetCore.Configuration.DynamicCacheBusting.Version")] diff --git a/src/Cuemon.Core/GlobalSuppressions.cs b/src/Cuemon.Core/GlobalSuppressions.cs index 93f956fe..19521d39 100644 --- a/src/Cuemon.Core/GlobalSuppressions.cs +++ b/src/Cuemon.Core/GlobalSuppressions.cs @@ -260,3 +260,5 @@ [assembly: SuppressMessage("Design", "CA1000:Do not declare static members on generic types", Justification = "By design; supports consistent developer experience for all formatters, e.g., SerializeObject/DeserializeObject.", Scope = "member", Target = "~M:Cuemon.Runtime.Serialization.Formatters.StreamFormatter`1.SerializeObject(System.Object,System.Type,`0)~System.IO.Stream")] [assembly: SuppressMessage("Design", "CA1000:Do not declare static members on generic types", Justification = "By design; supports consistent developer experience for all formatters, e.g., SerializeObject/DeserializeObject.", Scope = "member", Target = "~M:Cuemon.Runtime.Serialization.Formatters.StreamFormatter`1.SerializeObject(System.Object,System.Type,System.Action{`0})~System.IO.Stream")] [assembly: SuppressMessage("Globalization", "CA1304:Specify CultureInfo", Justification = "False-Positive. Overload exists.", Scope = "member", Target = "~M:Cuemon.DateSpan.Parse(System.String)~Cuemon.DateSpan")] +[assembly: SuppressMessage("Globalization", "CA1305:Specify IFormatProvider", Justification = "Not relevant in this context.", Scope = "member", Target = "~M:Cuemon.Runtime.Serialization.HierarchySerializer.ToString(System.Text.StringBuilder,Cuemon.IHierarchy{System.Object})")] +[assembly: SuppressMessage("Globalization", "CA1304:Specify CultureInfo", Justification = "Intentionally written for only en-US support.", Scope = "member", Target = "~M:Cuemon.Reflection.MemberArgumentDecoratorExtensions.CreateException(Cuemon.IDecorator{System.Collections.Generic.Stack{System.Collections.Generic.IList{Cuemon.Reflection.MemberArgument}}},System.Boolean)~System.Exception")] diff --git a/src/Cuemon.Extensions.AspNetCore/GlobalSuppressions.cs b/src/Cuemon.Extensions.AspNetCore/GlobalSuppressions.cs index c333543f..32d27ebf 100644 --- a/src/Cuemon.Extensions.AspNetCore/GlobalSuppressions.cs +++ b/src/Cuemon.Extensions.AspNetCore/GlobalSuppressions.cs @@ -6,3 +6,4 @@ using System.Diagnostics.CodeAnalysis; [assembly: SuppressMessage("Performance", "CA1835:Prefer the 'Memory'-based overloads for 'ReadAsync' and 'WriteAsync'", Justification = "Already fixed for .NET 5, but SonarCloud cannot figure out multiple framework support, eg. NETStandard 2.", Scope = "member", Target = "~M:Cuemon.Extensions.AspNetCore.Http.HttpResponseExtensions.WriteBodyAsync(Microsoft.AspNetCore.Http.HttpResponse,System.Func{System.Byte[]})~System.Threading.Tasks.Task")] +[assembly: SuppressMessage("Globalization", "CA1304:Specify CultureInfo", Justification = "Not relevant in this context.", Scope = "member", Target = "~M:Cuemon.Extensions.AspNetCore.Configuration.AssemblyCacheBusting.#ctor(Microsoft.Extensions.Options.IOptions{Cuemon.Extensions.AspNetCore.Configuration.AssemblyCacheBustingOptions})")] From e22eef7a4cd742d5e1a37d6235e8515ccc4dcedf Mon Sep 17 00:00:00 2001 From: Michael Mortensen Date: Sat, 14 Sep 2024 16:51:45 +0200 Subject: [PATCH 07/37] :rotating_light: https://learn.microsoft.com/en-us/dotnet/fundamentals/code-analysis/quality-rules/ca1305 --- .../Digest/DigestAuthorizationHeader.cs | 5 +++-- .../Digest/DigestAuthorizationHeaderBuilder.cs | 4 ++-- .../Hmac/HmacAuthorizationHeaderBuilder.cs | 2 +- .../Filters/Diagnostics/ServerTimingFilter.cs | 2 +- .../Diagnostics/ServerTimingMiddleware.cs | 2 +- src/Cuemon.AspNetCore/Http/HttpStatusCodeException.cs | 2 +- src/Cuemon.Core/DayPart.cs | 5 +++-- .../Reflection/MemberArgumentDecoratorExtensions.cs | 3 ++- src/Cuemon.Core/Generate.cs | 2 +- src/Cuemon.Core/Security/FowlerNollVo1024.cs | 8 ++++++-- src/Cuemon.Core/Security/FowlerNollVo128.cs | 8 ++++++-- src/Cuemon.Core/Security/FowlerNollVo256.cs | 8 ++++++-- src/Cuemon.Core/Security/FowlerNollVo32.cs | 6 +++++- src/Cuemon.Core/Security/FowlerNollVo512.cs | 8 ++++++-- src/Cuemon.Core/Security/FowlerNollVo64.cs | 8 ++++++-- src/Cuemon.Core/Validator.cs | 2 +- src/Cuemon.Data/DataReader.cs | 4 ++-- src/Cuemon.Data/DataTransferRow.cs | 4 ++-- .../Converters/XmlConverterExtensions.cs | 2 +- .../Text/Yaml/Converters/YamlConverterExtensions.cs | 3 ++- src/Cuemon.Extensions.Core/StringExtensions.cs | 2 +- .../Specialized/NameValueCollectionDecoratorExtensions.cs | 8 ++++---- .../Converters/XmlConverterDecoratorExtensions.cs | 2 +- 23 files changed, 64 insertions(+), 36 deletions(-) diff --git a/src/Cuemon.AspNetCore.Authentication/Digest/DigestAuthorizationHeader.cs b/src/Cuemon.AspNetCore.Authentication/Digest/DigestAuthorizationHeader.cs index 9783a180..b524d13e 100644 --- a/src/Cuemon.AspNetCore.Authentication/Digest/DigestAuthorizationHeader.cs +++ b/src/Cuemon.AspNetCore.Authentication/Digest/DigestAuthorizationHeader.cs @@ -1,5 +1,6 @@ using System; using System.Collections.Generic; +using System.Globalization; using System.Text; using Cuemon.Net.Http; @@ -177,7 +178,7 @@ public override string ToString() private static void AppendField(StringBuilder sb, string fn, string fv) { - if (!string.IsNullOrWhiteSpace(fv)) { sb.Append($" {fn}=\"{fv}\""); } + if (!string.IsNullOrWhiteSpace(fv)) { sb.Append(CultureInfo.InvariantCulture, $" {fn}=\"{fv}\""); } } } -} \ No newline at end of file +} diff --git a/src/Cuemon.AspNetCore.Authentication/Digest/DigestAuthorizationHeaderBuilder.cs b/src/Cuemon.AspNetCore.Authentication/Digest/DigestAuthorizationHeaderBuilder.cs index d398e2f6..aedfbe6d 100644 --- a/src/Cuemon.AspNetCore.Authentication/Digest/DigestAuthorizationHeaderBuilder.cs +++ b/src/Cuemon.AspNetCore.Authentication/Digest/DigestAuthorizationHeaderBuilder.cs @@ -82,7 +82,7 @@ public DigestAuthorizationHeaderBuilder AddUri(string digestUri) public DigestAuthorizationHeaderBuilder AddNc(int nonceCount) { Validator.ThrowIfLowerThan(nonceCount, 0, nameof(nonceCount)); - return AddOrUpdate(DigestFields.NonceCount, nonceCount.ToString("x8")); + return AddOrUpdate(DigestFields.NonceCount, nonceCount.ToString("x8", CultureInfo.InvariantCulture)); } /// @@ -270,4 +270,4 @@ public override DigestAuthorizationHeader Build() Data[DigestFields.Response]); } } -} \ No newline at end of file +} diff --git a/src/Cuemon.AspNetCore.Authentication/Hmac/HmacAuthorizationHeaderBuilder.cs b/src/Cuemon.AspNetCore.Authentication/Hmac/HmacAuthorizationHeaderBuilder.cs index 5821f705..66b004c3 100644 --- a/src/Cuemon.AspNetCore.Authentication/Hmac/HmacAuthorizationHeaderBuilder.cs +++ b/src/Cuemon.AspNetCore.Authentication/Hmac/HmacAuthorizationHeaderBuilder.cs @@ -135,7 +135,7 @@ public override string ComputeSignature() Decorator.Enclose(Data).GetValueOrDefault(HmacFields.CredentialScope), Alphanumeric.Linefeed, ComputeCanonicalRequest()); - var date = DateTime.Parse(Data[HmacFields.ServerDateTime], CultureInfo.InvariantCulture, DateTimeStyles.RoundtripKind).Date.ToString("yyyyMMdd"); + var date = DateTime.Parse(Data[HmacFields.ServerDateTime], CultureInfo.InvariantCulture, DateTimeStyles.RoundtripKind).Date.ToString("yyyyMMdd", CultureInfo.InvariantCulture); var dateSecret = KeyedHashFactory.CreateHmacCrypto(secret, HmacAlgorithm).ComputeHash(date).GetBytes(); AddOrUpdate(HmacFields.StringToSign, stringToSign); diff --git a/src/Cuemon.AspNetCore.Mvc/Filters/Diagnostics/ServerTimingFilter.cs b/src/Cuemon.AspNetCore.Mvc/Filters/Diagnostics/ServerTimingFilter.cs index fdce9ea7..24c7649f 100644 --- a/src/Cuemon.AspNetCore.Mvc/Filters/Diagnostics/ServerTimingFilter.cs +++ b/src/Cuemon.AspNetCore.Mvc/Filters/Diagnostics/ServerTimingFilter.cs @@ -104,7 +104,7 @@ public override void OnActionExecuted(ActionExecutedContext context) var logLevel = Options.LogLevelSelector(metric); Logger.Log(logLevel, "ServerTimingMetric {{ Name: {Name}, Duration: {Duration}ms, Description: \"{Description}\" }}", metric.Name, - metric.Duration?.TotalMilliseconds.ToString("F1", CultureInfo.InvariantCulture) ?? 0.ToString("F1"), + metric.Duration?.TotalMilliseconds.ToString("F1", CultureInfo.InvariantCulture) ?? 0.ToString("F1", CultureInfo.InvariantCulture), metric.Description ?? "N/A"); } } diff --git a/src/Cuemon.AspNetCore/Diagnostics/ServerTimingMiddleware.cs b/src/Cuemon.AspNetCore/Diagnostics/ServerTimingMiddleware.cs index aea88566..44ba877c 100644 --- a/src/Cuemon.AspNetCore/Diagnostics/ServerTimingMiddleware.cs +++ b/src/Cuemon.AspNetCore/Diagnostics/ServerTimingMiddleware.cs @@ -49,7 +49,7 @@ public override Task InvokeAsync(HttpContext context, ILogger pi.CanRead && Decorator.Enclose(pi.DeclaringType).HasTypes(typeof(HttpStatusCodeException)))) { var value = Patterns.InvokeOrDefault(() => pi.GetValue(this, null)); // we cannot risk exceptions being thrown in a ToString method - if (value != null) { sb.AppendLine($"{Alphanumeric.Tab}{pi.Name}: {value}"); } + if (value != null) { sb.AppendLine(CultureInfo.InvariantCulture, $"{Alphanumeric.Tab}{pi.Name}: {value}"); } } return sb.ToString(); } diff --git a/src/Cuemon.Core/DayPart.cs b/src/Cuemon.Core/DayPart.cs index 8accbf47..5a18f6fb 100644 --- a/src/Cuemon.Core/DayPart.cs +++ b/src/Cuemon.Core/DayPart.cs @@ -1,5 +1,6 @@ using System; using System.Collections.Generic; +using System.Globalization; namespace Cuemon { @@ -88,7 +89,7 @@ public DayPart(string name, TimeRange range) /// A that represents this instance. public override string ToString() { - return FormattableString.Invariant($"{Name} ({Range.Start.ToString("t")} - {Range.End.ToString("t")})"); + return FormattableString.Invariant($"{Name} ({Range.Start.ToString("t", CultureInfo.InvariantCulture)} - {Range.End.ToString("t", CultureInfo.InvariantCulture)})"); } } -} \ No newline at end of file +} diff --git a/src/Cuemon.Core/Extensions/Reflection/MemberArgumentDecoratorExtensions.cs b/src/Cuemon.Core/Extensions/Reflection/MemberArgumentDecoratorExtensions.cs index fe8d742f..21d48677 100644 --- a/src/Cuemon.Core/Extensions/Reflection/MemberArgumentDecoratorExtensions.cs +++ b/src/Cuemon.Core/Extensions/Reflection/MemberArgumentDecoratorExtensions.cs @@ -1,5 +1,6 @@ using System; using System.Collections.Generic; +using System.Globalization; using System.Linq; using System.Resources; @@ -47,7 +48,7 @@ public static Exception CreateException(this IDecorator o.FullName = true))); var properties = instanceType.GetRuntimeProperties().Where(options.PropertiesPredicate); - instanceSignature.AppendFormat(" {{ {0} }}", DelimitedString.Create(properties, o => + instanceSignature.AppendFormat(options.FormatProvider, " {{ {0} }}", DelimitedString.Create(properties, o => { o.Delimiter = options.Delimiter; o.StringConverter = pi => options.PropertyConverter(pi, instance, options.FormatProvider); diff --git a/src/Cuemon.Core/Security/FowlerNollVo1024.cs b/src/Cuemon.Core/Security/FowlerNollVo1024.cs index 031d979c..b8f0489f 100644 --- a/src/Cuemon.Core/Security/FowlerNollVo1024.cs +++ b/src/Cuemon.Core/Security/FowlerNollVo1024.cs @@ -1,4 +1,5 @@ using System; +using System.Globalization; using System.Numerics; namespace Cuemon.Security @@ -14,8 +15,11 @@ public sealed class FowlerNollVo1024 : FowlerNollVoHash /// Initializes a new instance of the class. /// /// The which may be configured. - public FowlerNollVo1024(Action setup = null) : base(1024, BigInteger.Parse("5016456510113118655434598811035278955030765345404790744303017523831112055108147451509157692220295382716162651878526895249385292291816524375083746691371804094271873160484737966720260389217684476157468082573"), BigInteger.Parse("14197795064947621068722070641403218320880622795441933960878474914617582723252296732303717722150864096521202355549365628174669108571814760471015076148029755969804077320157692458563003215304957150157403644460363550505412711285966361610267868082893823963790439336411086884584107735010676915"), setup) + public FowlerNollVo1024(Action setup = null) : base(1024, + BigInteger.Parse("5016456510113118655434598811035278955030765345404790744303017523831112055108147451509157692220295382716162651878526895249385292291816524375083746691371804094271873160484737966720260389217684476157468082573", CultureInfo.InvariantCulture), + BigInteger.Parse("14197795064947621068722070641403218320880622795441933960878474914617582723252296732303717722150864096521202355549365628174669108571814760471015076148029755969804077320157692458563003215304957150157403644460363550505412711285966361610267868082893823963790439336411086884584107735010676915", CultureInfo.InvariantCulture), + setup) { } } -} \ No newline at end of file +} diff --git a/src/Cuemon.Core/Security/FowlerNollVo128.cs b/src/Cuemon.Core/Security/FowlerNollVo128.cs index 986957c5..a9df3291 100644 --- a/src/Cuemon.Core/Security/FowlerNollVo128.cs +++ b/src/Cuemon.Core/Security/FowlerNollVo128.cs @@ -1,4 +1,5 @@ using System; +using System.Globalization; using System.Numerics; namespace Cuemon.Security @@ -14,8 +15,11 @@ public sealed class FowlerNollVo128 : FowlerNollVoHash /// Initializes a new instance of the class. /// /// The which may be configured. - public FowlerNollVo128(Action setup = null) : base(128, BigInteger.Parse("309485009821345068724781371"), BigInteger.Parse("144066263297769815596495629667062367629"), setup) + public FowlerNollVo128(Action setup = null) : base(128, + BigInteger.Parse("309485009821345068724781371", CultureInfo.InvariantCulture), + BigInteger.Parse("144066263297769815596495629667062367629", CultureInfo.InvariantCulture), + setup) { } } -} \ No newline at end of file +} diff --git a/src/Cuemon.Core/Security/FowlerNollVo256.cs b/src/Cuemon.Core/Security/FowlerNollVo256.cs index a4bcc0be..6ce0e529 100644 --- a/src/Cuemon.Core/Security/FowlerNollVo256.cs +++ b/src/Cuemon.Core/Security/FowlerNollVo256.cs @@ -1,4 +1,5 @@ using System; +using System.Globalization; using System.Numerics; namespace Cuemon.Security @@ -14,8 +15,11 @@ public sealed class FowlerNollVo256 : FowlerNollVoHash /// Initializes a new instance of the class. /// /// The which may be configured. - public FowlerNollVo256(Action setup = null) : base(256, BigInteger.Parse("374144419156711147060143317175368453031918731002211"), BigInteger.Parse("100029257958052580907070968620625704837092796014241193945225284501741471925557"), setup) + public FowlerNollVo256(Action setup = null) : base(256, + BigInteger.Parse("374144419156711147060143317175368453031918731002211", CultureInfo.InvariantCulture), + BigInteger.Parse("100029257958052580907070968620625704837092796014241193945225284501741471925557", CultureInfo.InvariantCulture), + setup) { } } -} \ No newline at end of file +} diff --git a/src/Cuemon.Core/Security/FowlerNollVo32.cs b/src/Cuemon.Core/Security/FowlerNollVo32.cs index 2e75d80d..4ce578fd 100644 --- a/src/Cuemon.Core/Security/FowlerNollVo32.cs +++ b/src/Cuemon.Core/Security/FowlerNollVo32.cs @@ -1,4 +1,5 @@ using System; +using System.Globalization; using System.Numerics; namespace Cuemon.Security @@ -14,7 +15,10 @@ public sealed class FowlerNollVo32 : FowlerNollVoHash /// Initializes a new instance of the class. /// /// The which may be configured. - public FowlerNollVo32(Action setup = null) : base(32, BigInteger.Parse("16777619"), BigInteger.Parse("2166136261"), setup) + public FowlerNollVo32(Action setup = null) : base(32, + BigInteger.Parse("16777619", CultureInfo.InvariantCulture), + BigInteger.Parse("2166136261", CultureInfo.InvariantCulture), + setup) { } } diff --git a/src/Cuemon.Core/Security/FowlerNollVo512.cs b/src/Cuemon.Core/Security/FowlerNollVo512.cs index d6be422d..4d93cc19 100644 --- a/src/Cuemon.Core/Security/FowlerNollVo512.cs +++ b/src/Cuemon.Core/Security/FowlerNollVo512.cs @@ -1,4 +1,5 @@ using System; +using System.Globalization; using System.Numerics; namespace Cuemon.Security @@ -14,8 +15,11 @@ public sealed class FowlerNollVo512 : FowlerNollVoHash /// Initializes a new instance of the class. /// /// The which may be configured. - public FowlerNollVo512(Action setup = null) : base(512, BigInteger.Parse("35835915874844867368919076489095108449946327955754392558399825615420669938882575126094039892345713852759"), BigInteger.Parse("9659303129496669498009435400716310466090418745672637896108374329434462657994582932197716438449813051892206539805784495328239340083876191928701583869517785"), setup) + public FowlerNollVo512(Action setup = null) : base(512, + BigInteger.Parse("35835915874844867368919076489095108449946327955754392558399825615420669938882575126094039892345713852759", CultureInfo.InvariantCulture), + BigInteger.Parse("9659303129496669498009435400716310466090418745672637896108374329434462657994582932197716438449813051892206539805784495328239340083876191928701583869517785", CultureInfo.InvariantCulture), + setup) { } } -} \ No newline at end of file +} diff --git a/src/Cuemon.Core/Security/FowlerNollVo64.cs b/src/Cuemon.Core/Security/FowlerNollVo64.cs index badb8624..47a5a4ae 100644 --- a/src/Cuemon.Core/Security/FowlerNollVo64.cs +++ b/src/Cuemon.Core/Security/FowlerNollVo64.cs @@ -1,4 +1,5 @@ using System; +using System.Globalization; using System.Numerics; namespace Cuemon.Security @@ -14,8 +15,11 @@ public sealed class FowlerNollVo64 : FowlerNollVoHash /// Initializes a new instance of the class. /// /// The which may be configured. - public FowlerNollVo64(Action setup = null) : base(64, BigInteger.Parse("1099511628211"), BigInteger.Parse("14695981039346656037"), setup) + public FowlerNollVo64(Action setup = null) : base(64, + BigInteger.Parse("1099511628211", CultureInfo.InvariantCulture), + BigInteger.Parse("14695981039346656037", CultureInfo.InvariantCulture), + setup) { } } -} \ No newline at end of file +} diff --git a/src/Cuemon.Core/Validator.cs b/src/Cuemon.Core/Validator.cs index f948909f..54fad824 100644 --- a/src/Cuemon.Core/Validator.cs +++ b/src/Cuemon.Core/Validator.cs @@ -96,7 +96,7 @@ public static TResult CheckParameter(Func validator) } catch (Exception e) { - if (message?.Equals("{0} are not in a valid state.", StringComparison.InvariantCulture) ?? false) { message = string.Format(message, Patterns.InvokeOrDefault(() => Decorator.Enclose(typeof(TOptions)).ToFriendlyName(), "Options")); } + if (message?.Equals("{0} are not in a valid state.", StringComparison.InvariantCulture) ?? false) { message = string.Format(CultureInfo.InvariantCulture, message, Patterns.InvokeOrDefault(() => Decorator.Enclose(typeof(TOptions)).ToFriendlyName(), "Options")); } throw new ArgumentException(message, paramName, e); } } diff --git a/src/Cuemon.Data/DataReader.cs b/src/Cuemon.Data/DataReader.cs index 97ec8995..8175a389 100644 --- a/src/Cuemon.Data/DataReader.cs +++ b/src/Cuemon.Data/DataReader.cs @@ -69,7 +69,7 @@ public override string ToString() var builder = new StringBuilder(); for (var i = 0; i < FieldCount; i++) { - builder.AppendFormat("{0}={1}, ", GetName(i), GetValue(i)); + builder.AppendFormat(CultureInfo.InvariantCulture, "{0}={1}, ", GetName(i), GetValue(i)); } if (builder.Length > 0) { builder.Remove(builder.Length - 2, 2); } return builder.ToString(); @@ -361,4 +361,4 @@ string IDataRecord.GetDataTypeName(int i) return typeof(string).ToString(); } } -} \ No newline at end of file +} diff --git a/src/Cuemon.Data/DataTransferRow.cs b/src/Cuemon.Data/DataTransferRow.cs index c03a9c13..3b6cd54f 100644 --- a/src/Cuemon.Data/DataTransferRow.cs +++ b/src/Cuemon.Data/DataTransferRow.cs @@ -126,9 +126,9 @@ public override string ToString() for (var i = 0; i < Columns.Count; i++) { var column = Columns[i]; - builder.AppendFormat("{0}={1} [{2}],", column.Name, Main.Data[GetIndexLocation(column.Ordinal)], column.DataType.Name); + builder.AppendFormat(CultureInfo.InvariantCulture, "{0}={1} [{2}],", column.Name, Main.Data[GetIndexLocation(column.Ordinal)], column.DataType.Name); } return builder.ToString(0, builder.Length - 1); } } -} \ No newline at end of file +} diff --git a/src/Cuemon.Extensions.AspNetCore.Xml/Converters/XmlConverterExtensions.cs b/src/Cuemon.Extensions.AspNetCore.Xml/Converters/XmlConverterExtensions.cs index 8bd812b6..fcd614ec 100644 --- a/src/Cuemon.Extensions.AspNetCore.Xml/Converters/XmlConverterExtensions.cs +++ b/src/Cuemon.Extensions.AspNetCore.Xml/Converters/XmlConverterExtensions.cs @@ -37,7 +37,7 @@ private static void WriteProblemDetails(XmlWriter writer, ProblemDetails pd) writer.WriteStartElement(nameof(ProblemDetails)); if (pd.Type != null) { writer.WriteElementString(nameof(ProblemDetails.Type), pd.Type); } if (pd.Title != null) { writer.WriteElementString(nameof(ProblemDetails.Title), pd.Title); } - if (pd.Status.HasValue) { writer.WriteElementString(nameof(ProblemDetails.Status), pd.Status.Value.ToString()); } + if (pd.Status.HasValue) { writer.WriteElementString(nameof(ProblemDetails.Status), pd.Status.Value.ToString(CultureInfo.InvariantCulture)); } if (pd.Detail != null) { writer.WriteElementString(nameof(ProblemDetails.Detail), pd.Detail); } if (pd.Instance != null) { writer.WriteElementString(nameof(ProblemDetails.Instance), pd.Instance); } diff --git a/src/Cuemon.Extensions.AspNetCore/Text/Yaml/Converters/YamlConverterExtensions.cs b/src/Cuemon.Extensions.AspNetCore/Text/Yaml/Converters/YamlConverterExtensions.cs index 2755eeff..de719547 100644 --- a/src/Cuemon.Extensions.AspNetCore/Text/Yaml/Converters/YamlConverterExtensions.cs +++ b/src/Cuemon.Extensions.AspNetCore/Text/Yaml/Converters/YamlConverterExtensions.cs @@ -1,5 +1,6 @@ using System; using System.Collections.Generic; +using System.Globalization; using System.Linq; using Cuemon.AspNetCore.Diagnostics; using Cuemon.Diagnostics; @@ -42,7 +43,7 @@ public static ICollection AddHttpExceptionDescriptorConverter(thi writer.WritePropertyName(options.SetPropertyName("Error")); writer.WriteStartObject(); - writer.WriteString(options.SetPropertyName("Status"), value.StatusCode.ToString()); + writer.WriteString(options.SetPropertyName("Status"), value.StatusCode.ToString(CultureInfo.InvariantCulture)); writer.WriteString(options.SetPropertyName("Code"), value.Code); writer.WriteString(options.SetPropertyName("Message"), value.Message); if (value.HelpLink != null) diff --git a/src/Cuemon.Extensions.Core/StringExtensions.cs b/src/Cuemon.Extensions.Core/StringExtensions.cs index a93111d2..019ae3c9 100644 --- a/src/Cuemon.Extensions.Core/StringExtensions.cs +++ b/src/Cuemon.Extensions.Core/StringExtensions.cs @@ -846,7 +846,7 @@ public static TEnum ToEnum(this string value, bool ignoreCase = true) whe /// public static TimeSpan ToTimeSpan(this string value, TimeUnit timeUnit) { - return Decorator.Enclose(double.Parse(value)).ToTimeSpan(timeUnit); + return Decorator.Enclose(double.Parse(value, CultureInfo.InvariantCulture)).ToTimeSpan(timeUnit); } /// diff --git a/src/Cuemon.Net/Extensions/Collections/Specialized/NameValueCollectionDecoratorExtensions.cs b/src/Cuemon.Net/Extensions/Collections/Specialized/NameValueCollectionDecoratorExtensions.cs index c57c5223..3753864f 100644 --- a/src/Cuemon.Net/Extensions/Collections/Specialized/NameValueCollectionDecoratorExtensions.cs +++ b/src/Cuemon.Net/Extensions/Collections/Specialized/NameValueCollectionDecoratorExtensions.cs @@ -1,6 +1,7 @@ using System; using System.Collections.Specialized; using System.ComponentModel; +using System.Globalization; using System.Text; namespace Cuemon.Net.Collections.Specialized @@ -24,8 +25,7 @@ public static class NameValueCollectionDecoratorExtensions /// public static string ToString(this IDecorator decorator, FieldValueSeparator separator, bool urlEncode) { - Validator.ThrowIfNull(decorator); - var fieldValuePairs = decorator.Inner; + Validator.ThrowIfNull(decorator, out var fieldValuePairs); var characterSeparator = GetSeparator(separator); var builder = new StringBuilder(separator == FieldValueSeparator.Ampersand ? "?" : ""); foreach (string item in fieldValuePairs) @@ -33,7 +33,7 @@ public static string ToString(this IDecorator decorator, Fi var values = fieldValuePairs[item].Split(','); foreach (var value in values) { - builder.AppendFormat("{0}={1}", item, urlEncode ? Decorator.Enclose(Decorator.Enclose(value).UrlDecode()).UrlEncode() : value); + builder.AppendFormat(CultureInfo.InvariantCulture, "{0}={1}", item, urlEncode ? Decorator.Enclose(Decorator.Enclose(value).UrlDecode()).UrlEncode() : value); builder.Append(characterSeparator); } } @@ -53,4 +53,4 @@ internal static char GetSeparator(FieldValueSeparator separator) throw new InvalidEnumArgumentException(nameof(separator), (int)separator, typeof(FieldValueSeparator)); } } -} \ No newline at end of file +} diff --git a/src/Cuemon.Xml/Extensions/Serialization/Converters/XmlConverterDecoratorExtensions.cs b/src/Cuemon.Xml/Extensions/Serialization/Converters/XmlConverterDecoratorExtensions.cs index b598c0b5..85b4b228 100644 --- a/src/Cuemon.Xml/Extensions/Serialization/Converters/XmlConverterDecoratorExtensions.cs +++ b/src/Cuemon.Xml/Extensions/Serialization/Converters/XmlConverterDecoratorExtensions.cs @@ -260,7 +260,7 @@ public static IDecorator> AddTimeSpanConverter(this IDecorat }, (reader, _) => { var decoratorHierarchy = Decorator.Enclose(Decorator.Enclose(reader).ToHierarchy()); - return decoratorHierarchy.Inner.Instance.Type == typeof(DateTime) ? Decorator.Enclose(decoratorHierarchy.Inner.Instance.Value).ChangeTypeOrDefault().TimeOfDay : TimeSpan.Parse(decoratorHierarchy.Inner.Instance.Value.ToString()); + return decoratorHierarchy.Inner.Instance.Type == typeof(DateTime) ? Decorator.Enclose(decoratorHierarchy.Inner.Instance.Value).ChangeTypeOrDefault().TimeOfDay : TimeSpan.Parse(decoratorHierarchy.Inner.Instance.Value.ToString(), CultureInfo.InvariantCulture); }); return decorator; } From 974fd6b52c69e5feee0820e21b92e86b228c35d3 Mon Sep 17 00:00:00 2001 From: Michael Mortensen Date: Sat, 14 Sep 2024 16:57:00 +0200 Subject: [PATCH 08/37] :rotating_light: https://learn.microsoft.com/en-us/dotnet/fundamentals/code-analysis/quality-rules/ca1309 --- .../Extensions/Http/HttpRequestDecoratorExtensions.cs | 2 +- src/Cuemon.Core/Reflection/VersionResult.cs | 4 ++-- src/Cuemon.Core/Resilience/TransientFaultEvidence.cs | 5 ++++- src/Cuemon.Core/Validator.cs | 2 +- .../CultureInfoExtensions.cs | 2 +- .../JDataResultExtensions.cs | 6 ++++-- 6 files changed, 13 insertions(+), 8 deletions(-) diff --git a/src/Cuemon.AspNetCore/Extensions/Http/HttpRequestDecoratorExtensions.cs b/src/Cuemon.AspNetCore/Extensions/Http/HttpRequestDecoratorExtensions.cs index b7e73396..fdd8754b 100644 --- a/src/Cuemon.AspNetCore/Extensions/Http/HttpRequestDecoratorExtensions.cs +++ b/src/Cuemon.AspNetCore/Extensions/Http/HttpRequestDecoratorExtensions.cs @@ -55,7 +55,7 @@ public static bool IsClientSideResourceCached(this IDecorator decor clientSideEntityTag = clientSideEntityTag.Remove(indexOfEndQuote, 1); clientSideEntityTag = clientSideEntityTag.Remove(indexOfStartQuote, 1); } - return builder.Checksum.ToHexadecimalString().Equals(clientSideEntityTag); + return builder.Checksum.ToHexadecimalString().Equals(clientSideEntityTag, StringComparison.Ordinal); } return false; } diff --git a/src/Cuemon.Core/Reflection/VersionResult.cs b/src/Cuemon.Core/Reflection/VersionResult.cs index 81bc8308..421a4028 100644 --- a/src/Cuemon.Core/Reflection/VersionResult.cs +++ b/src/Cuemon.Core/Reflection/VersionResult.cs @@ -17,7 +17,7 @@ public class VersionResult /// The that represents a potential alphanumeric version. public VersionResult(string alphanumericVersion) { - if (Version.TryParse(alphanumericVersion, out var version) && version.ToString().Equals(alphanumericVersion)) + if (Version.TryParse(alphanumericVersion, out var version) && version.ToString().Equals(alphanumericVersion, StringComparison.Ordinal)) { _version = version; } @@ -113,4 +113,4 @@ public override string ToString() return Value; } } -} \ No newline at end of file +} diff --git a/src/Cuemon.Core/Resilience/TransientFaultEvidence.cs b/src/Cuemon.Core/Resilience/TransientFaultEvidence.cs index 6bddd976..2b50a76a 100644 --- a/src/Cuemon.Core/Resilience/TransientFaultEvidence.cs +++ b/src/Cuemon.Core/Resilience/TransientFaultEvidence.cs @@ -92,7 +92,10 @@ public virtual bool Equals(TransientFaultEvidence other) { if (other is null) { return false; } if (ReferenceEquals(this, other)) { return true; } - return Attempts == other.Attempts && RecoveryWaitTime.Equals(other.RecoveryWaitTime) && TotalRecoveryWaitTime.Equals(other.TotalRecoveryWaitTime) && Latency.Equals(other.Latency) && Descriptor.ToString().Equals(other.Descriptor.ToString()); + return Attempts == other.Attempts && + RecoveryWaitTime.Equals(other.RecoveryWaitTime) && + TotalRecoveryWaitTime.Equals(other.TotalRecoveryWaitTime) && + Latency.Equals(other.Latency) && Descriptor.ToString().Equals(other.Descriptor.ToString(), StringComparison.Ordinal); } /// diff --git a/src/Cuemon.Core/Validator.cs b/src/Cuemon.Core/Validator.cs index 54fad824..eae0846e 100644 --- a/src/Cuemon.Core/Validator.cs +++ b/src/Cuemon.Core/Validator.cs @@ -96,7 +96,7 @@ public static TResult CheckParameter(Func validator) } catch (Exception e) { - if (message?.Equals("{0} are not in a valid state.", StringComparison.InvariantCulture) ?? false) { message = string.Format(CultureInfo.InvariantCulture, message, Patterns.InvokeOrDefault(() => Decorator.Enclose(typeof(TOptions)).ToFriendlyName(), "Options")); } + if (message?.Equals("{0} are not in a valid state.", StringComparison.Ordinal) ?? false) { message = string.Format(CultureInfo.InvariantCulture, message, Patterns.InvokeOrDefault(() => Decorator.Enclose(typeof(TOptions)).ToFriendlyName(), "Options")); } throw new ArgumentException(message, paramName, e); } } diff --git a/src/Cuemon.Extensions.Globalization/CultureInfoExtensions.cs b/src/Cuemon.Extensions.Globalization/CultureInfoExtensions.cs index 7dec93fe..f8689196 100644 --- a/src/Cuemon.Extensions.Globalization/CultureInfoExtensions.cs +++ b/src/Cuemon.Extensions.Globalization/CultureInfoExtensions.cs @@ -50,7 +50,7 @@ public static IEnumerable UseNationalLanguageSupport(this IEnumerab var enrichedCultures = new List(); foreach (var culture in cultures) { - var enrichedCulture = EnrichedCultureInfos.Find(ci => ci.Name.Equals(culture.Name)); + var enrichedCulture = EnrichedCultureInfos.Find(ci => ci.Name.Equals(culture.Name, StringComparison.Ordinal)); if (enrichedCulture != null) { enrichedCultures.Add(enrichedCulture); diff --git a/src/Cuemon.Extensions.Newtonsoft.Json/JDataResultExtensions.cs b/src/Cuemon.Extensions.Newtonsoft.Json/JDataResultExtensions.cs index a9593e21..ce6e503a 100644 --- a/src/Cuemon.Extensions.Newtonsoft.Json/JDataResultExtensions.cs +++ b/src/Cuemon.Extensions.Newtonsoft.Json/JDataResultExtensions.cs @@ -88,7 +88,9 @@ public static void ExtractArrayValues(this IEnumerable source, stri private static bool HasMatchWithAsterisk(string s, string path) { - return s.EndsWith("*") && path.Contains('.') && s.Remove(s.LastIndexOf('.')).Equals(path.Remove(path.LastIndexOf('.'))); + return s.EndsWith("*") && + path.Contains('.') && + s.Remove(s.LastIndexOf('.')).Equals(path.Remove(path.LastIndexOf('.')), StringComparison.Ordinal); } } -} \ No newline at end of file +} From 7de8852f6b0e4ac699d774cf9df6256d7860786d Mon Sep 17 00:00:00 2001 From: Michael Mortensen Date: Sat, 14 Sep 2024 17:55:34 +0200 Subject: [PATCH 09/37] :rotating_light: https://learn.microsoft.com/en-us/dotnet/fundamentals/code-analysis/quality-rules/ca1310 --- src/Cuemon.AspNetCore.Authentication/AuthorizationHeader.cs | 2 +- .../Basic/BasicAuthorizationHeader.cs | 2 +- .../Digest/DigestAuthorizationHeaderBuilder.cs | 2 +- .../Reflection/MemberArgumentDecoratorExtensions.cs | 6 +++--- src/Cuemon.Core/Globalization/World.cs | 4 ++-- .../Http/HttpRequestExtensions.cs | 2 +- .../JDataResultExtensions.cs | 2 +- .../Serialization/Converters/ExceptionConverter.cs | 4 ++-- 8 files changed, 12 insertions(+), 12 deletions(-) diff --git a/src/Cuemon.AspNetCore.Authentication/AuthorizationHeader.cs b/src/Cuemon.AspNetCore.Authentication/AuthorizationHeader.cs index ecc05dfe..b7d858c4 100644 --- a/src/Cuemon.AspNetCore.Authentication/AuthorizationHeader.cs +++ b/src/Cuemon.AspNetCore.Authentication/AuthorizationHeader.cs @@ -35,7 +35,7 @@ protected AuthorizationHeader(string authenticationScheme) public virtual AuthorizationHeader Parse(string authorizationHeader, Action setup) { Validator.ThrowIfNullOrWhitespace(authorizationHeader); - Validator.ThrowIfFalse(() => authorizationHeader.StartsWith(AuthenticationScheme), nameof(authorizationHeader), $"Header did not start with {AuthenticationScheme}."); + Validator.ThrowIfFalse(() => authorizationHeader.StartsWith(AuthenticationScheme, StringComparison.OrdinalIgnoreCase), nameof(authorizationHeader), $"Header did not start with {AuthenticationScheme}."); Validator.ThrowIfInvalidConfigurator(setup, out var options); var headerWithoutScheme = authorizationHeader.Remove(0, AuthenticationScheme.Length + 1); diff --git a/src/Cuemon.AspNetCore.Authentication/Basic/BasicAuthorizationHeader.cs b/src/Cuemon.AspNetCore.Authentication/Basic/BasicAuthorizationHeader.cs index e60214bb..e7ccec62 100644 --- a/src/Cuemon.AspNetCore.Authentication/Basic/BasicAuthorizationHeader.cs +++ b/src/Cuemon.AspNetCore.Authentication/Basic/BasicAuthorizationHeader.cs @@ -96,7 +96,7 @@ public override string ToString() public override AuthorizationHeader Parse(string authorizationHeader, Action setup) { Validator.ThrowIfNullOrWhitespace(authorizationHeader); - Validator.ThrowIfFalse(() => authorizationHeader.StartsWith(AuthenticationScheme), nameof(authorizationHeader), $"Header did not start with {AuthenticationScheme}."); + Validator.ThrowIfFalse(() => authorizationHeader.StartsWith(AuthenticationScheme, StringComparison.OrdinalIgnoreCase), nameof(authorizationHeader), $"Header did not start with {AuthenticationScheme}."); var headerWithoutScheme = authorizationHeader.Remove(0, AuthenticationScheme.Length + 1); var credentials = new Dictionary(StringComparer.OrdinalIgnoreCase) diff --git a/src/Cuemon.AspNetCore.Authentication/Digest/DigestAuthorizationHeaderBuilder.cs b/src/Cuemon.AspNetCore.Authentication/Digest/DigestAuthorizationHeaderBuilder.cs index aedfbe6d..de54154b 100644 --- a/src/Cuemon.AspNetCore.Authentication/Digest/DigestAuthorizationHeaderBuilder.cs +++ b/src/Cuemon.AspNetCore.Authentication/Digest/DigestAuthorizationHeaderBuilder.cs @@ -139,7 +139,7 @@ public DigestAuthorizationHeaderBuilder AddFromWwwAuthenticateHeader(IHeaderDict private DigestAuthorizationHeaderBuilder AddFromWwwAuthenticateHeader(string wwwAuthenticateHeader) { Validator.ThrowIfNull(wwwAuthenticateHeader); - Validator.ThrowIfFalse(() => wwwAuthenticateHeader.StartsWith(AuthenticationScheme), nameof(wwwAuthenticateHeader), $"Header did not start with {AuthenticationScheme}."); + Validator.ThrowIfFalse(() => wwwAuthenticateHeader.StartsWith(AuthenticationScheme, StringComparison.OrdinalIgnoreCase), nameof(wwwAuthenticateHeader), $"Header did not start with {AuthenticationScheme}."); var headerWithoutScheme = wwwAuthenticateHeader.Remove(0, AuthenticationScheme.Length + 1); var fields = DelimitedString.Split(headerWithoutScheme); foreach (var field in fields) diff --git a/src/Cuemon.Core/Extensions/Reflection/MemberArgumentDecoratorExtensions.cs b/src/Cuemon.Core/Extensions/Reflection/MemberArgumentDecoratorExtensions.cs index 21d48677..72030c8f 100644 --- a/src/Cuemon.Core/Extensions/Reflection/MemberArgumentDecoratorExtensions.cs +++ b/src/Cuemon.Core/Extensions/Reflection/MemberArgumentDecoratorExtensions.cs @@ -45,12 +45,12 @@ public static Exception CreateException(this IDecorator 0) { message.Value = messageValue.Remove(indexOfMicrosoftParamName); } } diff --git a/src/Cuemon.Core/Globalization/World.cs b/src/Cuemon.Core/Globalization/World.cs index de40dedf..55ba4f55 100644 --- a/src/Cuemon.Core/Globalization/World.cs +++ b/src/Cuemon.Core/Globalization/World.cs @@ -46,7 +46,7 @@ public static class World public static IEnumerable GetCultures(RegionInfo region) { Validator.ThrowIfNull(region); - return SpecificCultures.Value.Where(c => c.Name.EndsWith(region.TwoLetterISORegionName)); + return SpecificCultures.Value.Where(c => c.Name.EndsWith(region.TwoLetterISORegionName, StringComparison.Ordinal)); } } -} \ No newline at end of file +} diff --git a/src/Cuemon.Extensions.AspNetCore/Http/HttpRequestExtensions.cs b/src/Cuemon.Extensions.AspNetCore/Http/HttpRequestExtensions.cs index 70d842cb..c47506c8 100644 --- a/src/Cuemon.Extensions.AspNetCore/Http/HttpRequestExtensions.cs +++ b/src/Cuemon.Extensions.AspNetCore/Http/HttpRequestExtensions.cs @@ -27,7 +27,7 @@ public static IEnumerable AcceptMimeTypesOrderedByQuality(this HttpReque .OrderByDescending(accept => { var values = accept.Split(';').Select(raw => raw.Trim()); - return values.FirstOrDefault(quality => quality.StartsWith("q=")) ?? "q=0.0"; + return values.FirstOrDefault(quality => quality.StartsWith("q=", StringComparison.OrdinalIgnoreCase)) ?? "q=0.0"; }) .Select(accept => accept.Split(';')[0]) .ToList(); diff --git a/src/Cuemon.Extensions.Newtonsoft.Json/JDataResultExtensions.cs b/src/Cuemon.Extensions.Newtonsoft.Json/JDataResultExtensions.cs index ce6e503a..7cbdf3f8 100644 --- a/src/Cuemon.Extensions.Newtonsoft.Json/JDataResultExtensions.cs +++ b/src/Cuemon.Extensions.Newtonsoft.Json/JDataResultExtensions.cs @@ -88,7 +88,7 @@ public static void ExtractArrayValues(this IEnumerable source, stri private static bool HasMatchWithAsterisk(string s, string path) { - return s.EndsWith("*") && + return s.EndsWith("*", StringComparison.Ordinal) && path.Contains('.') && s.Remove(s.LastIndexOf('.')).Equals(path.Remove(path.LastIndexOf('.')), StringComparison.Ordinal); } diff --git a/src/Cuemon.Xml/Serialization/Converters/ExceptionConverter.cs b/src/Cuemon.Xml/Serialization/Converters/ExceptionConverter.cs index c166f16f..2bd418c8 100644 --- a/src/Cuemon.Xml/Serialization/Converters/ExceptionConverter.cs +++ b/src/Cuemon.Xml/Serialization/Converters/ExceptionConverter.cs @@ -77,7 +77,7 @@ private static Stack> ParseXmlReader(XmlReader reader, Typ switch (reader.NodeType) { case XmlNodeType.Element: - exception = reader.Name.EndsWith("Exception") ? reader.Name : lastException; + exception = reader.Name.EndsWith("Exception", StringComparison.Ordinal) ? reader.Name : lastException; if (blueprints.Count > 0 && blueprints.Single(ma => ma.Name == "Type") is { } typeOfException @@ -129,7 +129,7 @@ private static string MapOrDefault(string memberName) { switch (memberName.ToLowerInvariant()) { - case { } when memberName.EndsWith("Exception"): + case { } when memberName.EndsWith("Exception", StringComparison.Ordinal): return nameof(Exception.InnerException); case "Stack": return nameof(Exception.StackTrace); From 63c44c910456ceb88a8a04834b57532c1082a83e Mon Sep 17 00:00:00 2001 From: Michael Mortensen Date: Sat, 14 Sep 2024 18:03:29 +0200 Subject: [PATCH 10/37] :rotating_light: https://learn.microsoft.com/en-us/dotnet/fundamentals/code-analysis/quality-rules/ca1710 --- src/Cuemon.AspNetCore/GlobalSuppressions.cs | 1 + src/Cuemon.Core/GlobalSuppressions.cs | 1 + 2 files changed, 2 insertions(+) diff --git a/src/Cuemon.AspNetCore/GlobalSuppressions.cs b/src/Cuemon.AspNetCore/GlobalSuppressions.cs index c03c8e0c..b2816a51 100644 --- a/src/Cuemon.AspNetCore/GlobalSuppressions.cs +++ b/src/Cuemon.AspNetCore/GlobalSuppressions.cs @@ -20,3 +20,4 @@ [assembly: SuppressMessage("Style", "IDE0130:Namespace does not match folder structure", Justification = "Intentional as these embark on IDecorator.", Scope = "namespace", Target = "~N:Cuemon.AspNetCore.Http")] [assembly: SuppressMessage("Style", "IDE0130:Namespace does not match folder structure", Justification = "Intentional as these embark on IDecorator.", Scope = "namespace", Target = "~N:Cuemon.AspNetCore.Http.Headers")] [assembly: SuppressMessage("Globalization", "CA1304:Specify CultureInfo", Justification = "Not relevant in this context.", Scope = "member", Target = "~P:Cuemon.AspNetCore.Configuration.DynamicCacheBusting.Version")] +[assembly: SuppressMessage("Naming", "CA1710:Identifiers should have correct suffix", Justification = "Suffix left out for clarity on intent.", Scope = "type", Target = "~T:Cuemon.AspNetCore.Http.Throttling.IThrottlingCache")] diff --git a/src/Cuemon.Core/GlobalSuppressions.cs b/src/Cuemon.Core/GlobalSuppressions.cs index 19521d39..9046b8e0 100644 --- a/src/Cuemon.Core/GlobalSuppressions.cs +++ b/src/Cuemon.Core/GlobalSuppressions.cs @@ -262,3 +262,4 @@ [assembly: SuppressMessage("Globalization", "CA1304:Specify CultureInfo", Justification = "False-Positive. Overload exists.", Scope = "member", Target = "~M:Cuemon.DateSpan.Parse(System.String)~Cuemon.DateSpan")] [assembly: SuppressMessage("Globalization", "CA1305:Specify IFormatProvider", Justification = "Not relevant in this context.", Scope = "member", Target = "~M:Cuemon.Runtime.Serialization.HierarchySerializer.ToString(System.Text.StringBuilder,Cuemon.IHierarchy{System.Object})")] [assembly: SuppressMessage("Globalization", "CA1304:Specify CultureInfo", Justification = "Intentionally written for only en-US support.", Scope = "member", Target = "~M:Cuemon.Reflection.MemberArgumentDecoratorExtensions.CreateException(Cuemon.IDecorator{System.Collections.Generic.Stack{System.Collections.Generic.IList{Cuemon.Reflection.MemberArgument}}},System.Boolean)~System.Exception")] +[assembly: SuppressMessage("Naming", "CA1710:Identifiers should have correct suffix", Justification = "Explicit implementation.", Scope = "type", Target = "~T:Cuemon.Diagnostics.Failure")] From ceeff26b8b801c26958e1cdd760478c49ab13959 Mon Sep 17 00:00:00 2001 From: Michael Mortensen Date: Sat, 14 Sep 2024 18:11:43 +0200 Subject: [PATCH 11/37] :rotating_light: https://learn.microsoft.com/en-us/dotnet/fundamentals/code-analysis/quality-rules/ca1805 --- .../Filters/Diagnostics/ServerTimingAttribute.cs | 2 +- .../RestfulApiVersioningOptions.cs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Cuemon.AspNetCore.Mvc/Filters/Diagnostics/ServerTimingAttribute.cs b/src/Cuemon.AspNetCore.Mvc/Filters/Diagnostics/ServerTimingAttribute.cs index c172683d..30e4b2c1 100644 --- a/src/Cuemon.AspNetCore.Mvc/Filters/Diagnostics/ServerTimingAttribute.cs +++ b/src/Cuemon.AspNetCore.Mvc/Filters/Diagnostics/ServerTimingAttribute.cs @@ -37,7 +37,7 @@ public ServerTimingAttribute() /// Gets or sets the value that in combination with specifies the threshold of the action method. /// /// The threshold value of the action method. - public double Threshold { get; set; } = 0; + public double Threshold { get; set; } /// /// Gets or sets one of the enumeration values that specifies the time unit of . diff --git a/src/Cuemon.Extensions.Asp.Versioning/RestfulApiVersioningOptions.cs b/src/Cuemon.Extensions.Asp.Versioning/RestfulApiVersioningOptions.cs index 008e5fb9..4f037838 100644 --- a/src/Cuemon.Extensions.Asp.Versioning/RestfulApiVersioningOptions.cs +++ b/src/Cuemon.Extensions.Asp.Versioning/RestfulApiVersioningOptions.cs @@ -136,7 +136,7 @@ public RestfulApiVersioningOptions UseProblemDetailsFactory() where T : class /// Gets or sets a value indicating whether responses will be based on the built in support for RFC 7807. /// /// true if the responses will be based on the built in support for RFC 7807; otherwise, false. - public bool UseBuiltInRfc7807 { get; set; } = false; + public bool UseBuiltInRfc7807 { get; set; } #endif /// From bc0431ebf590877285b990296c5d1649ecd1e0ca Mon Sep 17 00:00:00 2001 From: Michael Mortensen Date: Sat, 14 Sep 2024 23:28:22 +0200 Subject: [PATCH 12/37] :rotating_light: https://learn.microsoft.com/en-us/dotnet/fundamentals/code-analysis/quality-rules/ca1848 --- src/Cuemon.AspNetCore.Mvc/GlobalSuppressions.cs | 1 + src/Cuemon.AspNetCore/GlobalSuppressions.cs | 1 + .../GlobalSuppressions.cs | 8 ++++++++ 3 files changed, 10 insertions(+) create mode 100644 src/Cuemon.Extensions.AspNetCore.Authentication/GlobalSuppressions.cs diff --git a/src/Cuemon.AspNetCore.Mvc/GlobalSuppressions.cs b/src/Cuemon.AspNetCore.Mvc/GlobalSuppressions.cs index ab7fb8d8..9033b227 100644 --- a/src/Cuemon.AspNetCore.Mvc/GlobalSuppressions.cs +++ b/src/Cuemon.AspNetCore.Mvc/GlobalSuppressions.cs @@ -10,3 +10,4 @@ [assembly: SuppressMessage("Major Code Smell", "S1066:Collapsible \"if\" statements should be merged", Justification = "By design; easier for debug purposes and with clear scope.", Scope = "member", Target = "~M:Cuemon.AspNetCore.Mvc.Filters.Cacheable.HttpEntityTagHeaderFilter.OnResultExecutionAsync(Microsoft.AspNetCore.Mvc.Filters.ResultExecutingContext,Microsoft.AspNetCore.Mvc.Filters.ResultExecutionDelegate)~System.Threading.Tasks.Task")] [assembly: SuppressMessage("Critical Code Smell", "S3776:Cognitive Complexity of methods should not be too high", Justification = "If i invert the if-statement, the warning goes away - but the code becomes harder to read. So for now, i exclude it as 'by design'.", Scope = "member", Target = "~M:Cuemon.AspNetCore.Mvc.Filters.Diagnostics.FaultDescriptorFilter.OnException(Microsoft.AspNetCore.Mvc.Filters.ExceptionContext)")] [assembly: SuppressMessage("Minor Code Smell", "S3236:Caller information arguments should not be provided explicitly", Justification = "Intentional.", Scope = "member", Target = "~M:Cuemon.AspNetCore.Mvc.Filters.Diagnostics.FaultDescriptorFilter.#ctor(Microsoft.Extensions.Options.IOptions{Cuemon.AspNetCore.Mvc.Filters.Diagnostics.MvcFaultDescriptorOptions})")] +[assembly: SuppressMessage("Performance", "CA1848:Use the LoggerMessage delegates", Justification = "Lack support for dynamic log-level.", Scope = "member", Target = "~M:Cuemon.AspNetCore.Mvc.Filters.Diagnostics.ServerTimingFilter.OnActionExecuted(Microsoft.AspNetCore.Mvc.Filters.ActionExecutedContext)")] diff --git a/src/Cuemon.AspNetCore/GlobalSuppressions.cs b/src/Cuemon.AspNetCore/GlobalSuppressions.cs index b2816a51..deb6a4ed 100644 --- a/src/Cuemon.AspNetCore/GlobalSuppressions.cs +++ b/src/Cuemon.AspNetCore/GlobalSuppressions.cs @@ -21,3 +21,4 @@ [assembly: SuppressMessage("Style", "IDE0130:Namespace does not match folder structure", Justification = "Intentional as these embark on IDecorator.", Scope = "namespace", Target = "~N:Cuemon.AspNetCore.Http.Headers")] [assembly: SuppressMessage("Globalization", "CA1304:Specify CultureInfo", Justification = "Not relevant in this context.", Scope = "member", Target = "~P:Cuemon.AspNetCore.Configuration.DynamicCacheBusting.Version")] [assembly: SuppressMessage("Naming", "CA1710:Identifiers should have correct suffix", Justification = "Suffix left out for clarity on intent.", Scope = "type", Target = "~T:Cuemon.AspNetCore.Http.Throttling.IThrottlingCache")] +[assembly: SuppressMessage("Performance", "CA1848:Use the LoggerMessage delegates", Justification = "Lack support for dynamic log-level.", Scope = "member", Target = "~M:Cuemon.AspNetCore.Diagnostics.ServerTimingMiddleware.InvokeAsync(Microsoft.AspNetCore.Http.HttpContext,Microsoft.Extensions.Logging.ILogger{Cuemon.AspNetCore.Diagnostics.ServerTimingMiddleware},Microsoft.Extensions.Hosting.IHostEnvironment,Cuemon.AspNetCore.Diagnostics.IServerTiming,Microsoft.Extensions.Options.IOptions{Cuemon.AspNetCore.Diagnostics.ServerTimingOptions})~System.Threading.Tasks.Task")] diff --git a/src/Cuemon.Extensions.AspNetCore.Authentication/GlobalSuppressions.cs b/src/Cuemon.Extensions.AspNetCore.Authentication/GlobalSuppressions.cs new file mode 100644 index 00000000..27826659 --- /dev/null +++ b/src/Cuemon.Extensions.AspNetCore.Authentication/GlobalSuppressions.cs @@ -0,0 +1,8 @@ +// This file is used by Code Analysis to maintain SuppressMessage +// attributes that are applied to this project. +// Project-level suppressions either have no target or are given +// a specific target and scoped to a namespace, type, member, etc. + +using System.Diagnostics.CodeAnalysis; + +[assembly: SuppressMessage("Performance", "CA1848:Use the LoggerMessage delegates", Justification = "Should happen rarely.", Scope = "member", Target = "~M:Cuemon.Extensions.AspNetCore.Authentication.AuthorizationResponseHandler.HandleAsync(Microsoft.AspNetCore.Http.RequestDelegate,Microsoft.AspNetCore.Http.HttpContext,Microsoft.AspNetCore.Authorization.AuthorizationPolicy,Microsoft.AspNetCore.Authorization.Policy.PolicyAuthorizationResult)~System.Threading.Tasks.Task")] From 06383c75306bad57a6c286ebd94ccd0bd8beff98 Mon Sep 17 00:00:00 2001 From: Michael Mortensen Date: Sat, 14 Sep 2024 23:34:55 +0200 Subject: [PATCH 13/37] :rotating_light: https://learn.microsoft.com/en-us/dotnet/fundamentals/code-analysis/quality-rules/ca1852 --- src/Cuemon.AspNetCore.Mvc/ContentBasedObjectResult.cs | 4 ++-- src/Cuemon.AspNetCore.Mvc/ContentTimeBasedObjectResult.cs | 4 ++-- src/Cuemon.AspNetCore.Mvc/TimeBasedObjectResult.cs | 4 ++-- src/Cuemon.Core/Collections/Generic/DynamicComparer.cs | 4 ++-- .../Collections/Generic/DynamicEqualityComparer.cs | 4 ++-- src/Cuemon.Core/Collections/Generic/PartitionerEnumerator.cs | 4 ++-- src/Cuemon.Core/Diagnostics/ProcessInfo.cs | 4 ++-- src/Cuemon.Core/EnvironmentInfo.cs | 4 ++-- src/Cuemon.Core/StringReplaceCoordinate.cs | 4 ++-- src/Cuemon.Core/StringReplaceEngine.cs | 2 +- src/Cuemon.Core/Text/Parser.cs | 4 ++-- src/Cuemon.Core/Threading/ThreadInfo.cs | 4 ++-- src/Cuemon.Extensions.Net/Http/ActiveHandler.cs | 4 ++-- src/Cuemon.Extensions.Net/Http/ExpiredHandler.cs | 4 ++-- src/Cuemon.Extensions.Net/Http/TrackingHttpMessageHandler.cs | 4 ++-- .../DynamicContractResolver.cs | 4 ++-- src/Cuemon.Extensions.Newtonsoft.Json/DynamicJsonConverter.cs | 4 ++-- .../Converters/StringFlagsEnumConverter.cs | 2 +- src/Cuemon.Extensions.Text.Json/DynamicJsonConverter.cs | 4 ++-- src/Cuemon.Extensions.Xunit.Hosting/XunitTestLogger.cs | 2 +- .../XunitTestLoggerProvider.cs | 2 +- .../Formatters/PropertyTypeInspector.cs | 2 +- src/Cuemon.Extensions.YamlDotNet/YamlConverterFactory.cs | 4 ++-- src/Cuemon.Threading/AsyncForwardIterator.cs | 4 ++-- src/Cuemon.Threading/ForwardIterator.cs | 4 ++-- src/Cuemon.Xml/Serialization/DynamicXmlSerializable.cs | 4 ++-- 26 files changed, 47 insertions(+), 47 deletions(-) diff --git a/src/Cuemon.AspNetCore.Mvc/ContentBasedObjectResult.cs b/src/Cuemon.AspNetCore.Mvc/ContentBasedObjectResult.cs index 93e93269..8e666bcc 100644 --- a/src/Cuemon.AspNetCore.Mvc/ContentBasedObjectResult.cs +++ b/src/Cuemon.AspNetCore.Mvc/ContentBasedObjectResult.cs @@ -20,10 +20,10 @@ internal ContentBasedObjectResult(object instance, byte[] checksum, bool isWeak public HashResult Checksum { get; } } - internal class ContentBasedObjectResult : ContentBasedObjectResult + internal sealed class ContentBasedObjectResult : ContentBasedObjectResult { internal ContentBasedObjectResult(T instance, byte[] checksum, bool isWeak = false) : base(instance, checksum, isWeak) { } } -} \ No newline at end of file +} diff --git a/src/Cuemon.AspNetCore.Mvc/ContentTimeBasedObjectResult.cs b/src/Cuemon.AspNetCore.Mvc/ContentTimeBasedObjectResult.cs index 0c5bb10b..56efda2f 100644 --- a/src/Cuemon.AspNetCore.Mvc/ContentTimeBasedObjectResult.cs +++ b/src/Cuemon.AspNetCore.Mvc/ContentTimeBasedObjectResult.cs @@ -23,10 +23,10 @@ internal ContentTimeBasedObjectResult(object instance, IEntityDataTimestamp time public HashResult Checksum { get; set; } } - internal class ContentTimeBasedObjectResult : ContentTimeBasedObjectResult + internal sealed class ContentTimeBasedObjectResult : ContentTimeBasedObjectResult { internal ContentTimeBasedObjectResult(T instance, IEntityDataTimestamp timestamp, IEntityDataIntegrity dataIntegrity) : base(instance, timestamp, dataIntegrity) { } } -} \ No newline at end of file +} diff --git a/src/Cuemon.AspNetCore.Mvc/TimeBasedObjectResult.cs b/src/Cuemon.AspNetCore.Mvc/TimeBasedObjectResult.cs index 6e5631f9..87ca8225 100644 --- a/src/Cuemon.AspNetCore.Mvc/TimeBasedObjectResult.cs +++ b/src/Cuemon.AspNetCore.Mvc/TimeBasedObjectResult.cs @@ -16,10 +16,10 @@ internal TimeBasedObjectResult(object instance, DateTime created, DateTime? modi public DateTime? Modified { get; } } - internal class TimeBasedObjectResult : TimeBasedObjectResult + internal sealed class TimeBasedObjectResult : TimeBasedObjectResult { internal TimeBasedObjectResult(T instance, DateTime created, DateTime? modified) : base(instance, created, modified) { } } -} \ No newline at end of file +} diff --git a/src/Cuemon.Core/Collections/Generic/DynamicComparer.cs b/src/Cuemon.Core/Collections/Generic/DynamicComparer.cs index 4aeb4f84..1a230edc 100644 --- a/src/Cuemon.Core/Collections/Generic/DynamicComparer.cs +++ b/src/Cuemon.Core/Collections/Generic/DynamicComparer.cs @@ -20,7 +20,7 @@ public static IComparer Create(Func comparer) } } - internal class DynamicComparer : Comparer + internal sealed class DynamicComparer : Comparer { internal DynamicComparer(Func comparer) { @@ -36,4 +36,4 @@ public override int Compare(T x, T y) return Comparer(x, y); } } -} \ No newline at end of file +} diff --git a/src/Cuemon.Core/Collections/Generic/DynamicEqualityComparer.cs b/src/Cuemon.Core/Collections/Generic/DynamicEqualityComparer.cs index a7613d55..e00f7b12 100644 --- a/src/Cuemon.Core/Collections/Generic/DynamicEqualityComparer.cs +++ b/src/Cuemon.Core/Collections/Generic/DynamicEqualityComparer.cs @@ -22,7 +22,7 @@ public static IEqualityComparer Create(Func hashCalculator, Func : EqualityComparer + internal sealed class DynamicEqualityComparer : EqualityComparer { internal DynamicEqualityComparer(Func hashCalculator, Func equalityComparer) { @@ -47,4 +47,4 @@ public override int GetHashCode(T obj) return HashCalculator(obj); } } -} \ No newline at end of file +} diff --git a/src/Cuemon.Core/Collections/Generic/PartitionerEnumerator.cs b/src/Cuemon.Core/Collections/Generic/PartitionerEnumerator.cs index e98ca176..015fce95 100644 --- a/src/Cuemon.Core/Collections/Generic/PartitionerEnumerator.cs +++ b/src/Cuemon.Core/Collections/Generic/PartitionerEnumerator.cs @@ -4,7 +4,7 @@ namespace Cuemon.Collections.Generic { - internal class PartitionerEnumerator : Disposable, IEnumerator + internal sealed class PartitionerEnumerator : Disposable, IEnumerator { public PartitionerEnumerator(IEnumerator enumerator, int take, Action moveNextIncrementer, Action endOfSequenceNotifier) { @@ -63,4 +63,4 @@ protected override void OnDisposeManagedResources() Enumerator?.Dispose(); } } -} \ No newline at end of file +} diff --git a/src/Cuemon.Core/Diagnostics/ProcessInfo.cs b/src/Cuemon.Core/Diagnostics/ProcessInfo.cs index e6ff7c8c..92f2e299 100644 --- a/src/Cuemon.Core/Diagnostics/ProcessInfo.cs +++ b/src/Cuemon.Core/Diagnostics/ProcessInfo.cs @@ -6,7 +6,7 @@ namespace Cuemon.Diagnostics { - internal class ProcessInfo + internal sealed class ProcessInfo { internal ProcessInfo(Process process = null) { @@ -43,4 +43,4 @@ public override string ToString() return builder.ToString(); } } -} \ No newline at end of file +} diff --git a/src/Cuemon.Core/EnvironmentInfo.cs b/src/Cuemon.Core/EnvironmentInfo.cs index cf3d7d29..66bd5a63 100644 --- a/src/Cuemon.Core/EnvironmentInfo.cs +++ b/src/Cuemon.Core/EnvironmentInfo.cs @@ -6,7 +6,7 @@ namespace Cuemon { - internal class EnvironmentInfo + internal sealed class EnvironmentInfo { public override string ToString() { @@ -35,4 +35,4 @@ public override string ToString() return builder.ToString(); } } -} \ No newline at end of file +} diff --git a/src/Cuemon.Core/StringReplaceCoordinate.cs b/src/Cuemon.Core/StringReplaceCoordinate.cs index 545b8492..42f17c63 100644 --- a/src/Cuemon.Core/StringReplaceCoordinate.cs +++ b/src/Cuemon.Core/StringReplaceCoordinate.cs @@ -1,6 +1,6 @@ namespace Cuemon { - internal class StringReplaceCoordinate + internal sealed class StringReplaceCoordinate { internal StringReplaceCoordinate(int startIndex, int length, string value) { @@ -13,4 +13,4 @@ internal StringReplaceCoordinate(int startIndex, int length, string value) internal int Length { get; set; } internal string Value { get; set; } } -} \ No newline at end of file +} diff --git a/src/Cuemon.Core/StringReplaceEngine.cs b/src/Cuemon.Core/StringReplaceEngine.cs index 5bfe8330..20bb1578 100644 --- a/src/Cuemon.Core/StringReplaceEngine.cs +++ b/src/Cuemon.Core/StringReplaceEngine.cs @@ -6,7 +6,7 @@ namespace Cuemon { - internal class StringReplaceEngine + internal sealed class StringReplaceEngine { internal StringReplaceEngine(string value, IEnumerable replacePairs, StringComparison comparison) { diff --git a/src/Cuemon.Core/Text/Parser.cs b/src/Cuemon.Core/Text/Parser.cs index 722548af..69cbe046 100644 --- a/src/Cuemon.Core/Text/Parser.cs +++ b/src/Cuemon.Core/Text/Parser.cs @@ -3,7 +3,7 @@ namespace Cuemon.Text { - internal class Parser : IParser + internal sealed class Parser : IParser { private readonly Func _parser; @@ -102,4 +102,4 @@ public bool TryParse(string input, Type targetType, out object result, Action Parse(input, targetType, setup), out result); } } -} \ No newline at end of file +} diff --git a/src/Cuemon.Core/Threading/ThreadInfo.cs b/src/Cuemon.Core/Threading/ThreadInfo.cs index 2f5748cd..dc9f880a 100644 --- a/src/Cuemon.Core/Threading/ThreadInfo.cs +++ b/src/Cuemon.Core/Threading/ThreadInfo.cs @@ -4,7 +4,7 @@ namespace Cuemon.Threading { - internal class ThreadInfo + internal sealed class ThreadInfo { internal ThreadInfo(Thread thread = null) { @@ -41,4 +41,4 @@ public override string ToString() return builder.ToString(); } } -} \ No newline at end of file +} diff --git a/src/Cuemon.Extensions.Net/Http/ActiveHandler.cs b/src/Cuemon.Extensions.Net/Http/ActiveHandler.cs index e1347cab..7058dc80 100644 --- a/src/Cuemon.Extensions.Net/Http/ActiveHandler.cs +++ b/src/Cuemon.Extensions.Net/Http/ActiveHandler.cs @@ -2,7 +2,7 @@ namespace Cuemon.Extensions.Net.Http { - internal class ActiveHandler + internal sealed class ActiveHandler { public ActiveHandler(string name, DateTime expires, TrackingHttpMessageHandler handler) { @@ -17,4 +17,4 @@ public ActiveHandler(string name, DateTime expires, TrackingHttpMessageHandler h public TrackingHttpMessageHandler Handler { get; } } -} \ No newline at end of file +} diff --git a/src/Cuemon.Extensions.Net/Http/ExpiredHandler.cs b/src/Cuemon.Extensions.Net/Http/ExpiredHandler.cs index 041551cc..1b10a551 100644 --- a/src/Cuemon.Extensions.Net/Http/ExpiredHandler.cs +++ b/src/Cuemon.Extensions.Net/Http/ExpiredHandler.cs @@ -3,7 +3,7 @@ namespace Cuemon.Extensions.Net.Http { - internal class ExpiredHandler + internal sealed class ExpiredHandler { private readonly WeakReference _tracker; @@ -20,4 +20,4 @@ public ExpiredHandler(ActiveHandler origin) public HttpMessageHandler InnerHandler { get; } } -} \ No newline at end of file +} diff --git a/src/Cuemon.Extensions.Net/Http/TrackingHttpMessageHandler.cs b/src/Cuemon.Extensions.Net/Http/TrackingHttpMessageHandler.cs index c1ae70af..7337364e 100644 --- a/src/Cuemon.Extensions.Net/Http/TrackingHttpMessageHandler.cs +++ b/src/Cuemon.Extensions.Net/Http/TrackingHttpMessageHandler.cs @@ -2,7 +2,7 @@ namespace Cuemon.Extensions.Net.Http { - internal class TrackingHttpMessageHandler : DelegatingHandler + internal sealed class TrackingHttpMessageHandler : DelegatingHandler { public TrackingHttpMessageHandler(HttpMessageHandler inner) : base(inner) { @@ -13,4 +13,4 @@ protected override void Dispose(bool disposing) // The lifetime of this is tracked separately by ActiveHandler } } -} \ No newline at end of file +} diff --git a/src/Cuemon.Extensions.Newtonsoft.Json/DynamicContractResolver.cs b/src/Cuemon.Extensions.Newtonsoft.Json/DynamicContractResolver.cs index 40987efc..eaf87076 100644 --- a/src/Cuemon.Extensions.Newtonsoft.Json/DynamicContractResolver.cs +++ b/src/Cuemon.Extensions.Newtonsoft.Json/DynamicContractResolver.cs @@ -30,7 +30,7 @@ public static IContractResolver Create(T resolver, params Action> jsonPropertyHandlers) { @@ -50,7 +50,7 @@ protected override JsonProperty CreateProperty(MemberInfo member, MemberSerializ } } - internal class DynamicCamelCasePropertyNamesContractResolver : CamelCasePropertyNamesContractResolver + internal sealed class DynamicCamelCasePropertyNamesContractResolver : CamelCasePropertyNamesContractResolver { internal DynamicCamelCasePropertyNamesContractResolver(IEnumerable> jsonPropertyHandlers) { diff --git a/src/Cuemon.Extensions.Newtonsoft.Json/DynamicJsonConverter.cs b/src/Cuemon.Extensions.Newtonsoft.Json/DynamicJsonConverter.cs index b4ce924e..929f9ef8 100644 --- a/src/Cuemon.Extensions.Newtonsoft.Json/DynamicJsonConverter.cs +++ b/src/Cuemon.Extensions.Newtonsoft.Json/DynamicJsonConverter.cs @@ -74,7 +74,7 @@ public static JsonConverter Create(JsonConverter converter) } } - internal class DynamicJsonConverterCore : JsonConverter + internal sealed class DynamicJsonConverterCore : JsonConverter { internal DynamicJsonConverterCore(Func predicate, Action writer, Func reader, Type objectType = null, bool searchForNamingStrategy = false) { @@ -148,4 +148,4 @@ public override bool CanConvert(Type objectType) /// true if this can write JSON; otherwise, false. public override bool CanWrite => Writer != null; } -} \ No newline at end of file +} diff --git a/src/Cuemon.Extensions.Text.Json/Converters/StringFlagsEnumConverter.cs b/src/Cuemon.Extensions.Text.Json/Converters/StringFlagsEnumConverter.cs index d3fc89eb..60cf3bb1 100644 --- a/src/Cuemon.Extensions.Text.Json/Converters/StringFlagsEnumConverter.cs +++ b/src/Cuemon.Extensions.Text.Json/Converters/StringFlagsEnumConverter.cs @@ -41,7 +41,7 @@ public override JsonConverter CreateConverter(Type typeToConvert, JsonSerializer } } - internal class FlagsEnumConverter : JsonConverter + internal sealed class FlagsEnumConverter : JsonConverter { public FlagsEnumConverter(Type typeToConvert) { diff --git a/src/Cuemon.Extensions.Text.Json/DynamicJsonConverter.cs b/src/Cuemon.Extensions.Text.Json/DynamicJsonConverter.cs index bbb2096a..25baf025 100644 --- a/src/Cuemon.Extensions.Text.Json/DynamicJsonConverter.cs +++ b/src/Cuemon.Extensions.Text.Json/DynamicJsonConverter.cs @@ -61,7 +61,7 @@ public static JsonConverter Create(Func predicate, Func predicate, Func converterFactory) { @@ -84,7 +84,7 @@ public override JsonConverter CreateConverter(Type typeToConvert, JsonSerializer } } - internal class DynamicJsonConverter : JsonConverter + internal sealed class DynamicJsonConverter : JsonConverter { internal DynamicJsonConverter(Func predicate, Utf8JsonWriterAction writer, Utf8JsonReaderFunc reader) { diff --git a/src/Cuemon.Extensions.Xunit.Hosting/XunitTestLogger.cs b/src/Cuemon.Extensions.Xunit.Hosting/XunitTestLogger.cs index 8af387b5..010db65f 100644 --- a/src/Cuemon.Extensions.Xunit.Hosting/XunitTestLogger.cs +++ b/src/Cuemon.Extensions.Xunit.Hosting/XunitTestLogger.cs @@ -5,7 +5,7 @@ namespace Cuemon.Extensions.Xunit.Hosting { - internal class XunitTestLogger : InMemoryTestStore, ILogger, IDisposable + internal sealed class XunitTestLogger : InMemoryTestStore, ILogger, IDisposable { private readonly ITestOutputHelperAccessor _accessor; private readonly ITestOutputHelper _output; diff --git a/src/Cuemon.Extensions.Xunit.Hosting/XunitTestLoggerProvider.cs b/src/Cuemon.Extensions.Xunit.Hosting/XunitTestLoggerProvider.cs index a3c1cdc8..ebaa6273 100644 --- a/src/Cuemon.Extensions.Xunit.Hosting/XunitTestLoggerProvider.cs +++ b/src/Cuemon.Extensions.Xunit.Hosting/XunitTestLoggerProvider.cs @@ -4,7 +4,7 @@ namespace Cuemon.Extensions.Xunit.Hosting { - internal class XunitTestLoggerProvider : ILoggerProvider + internal sealed class XunitTestLoggerProvider : ILoggerProvider { private readonly ConcurrentDictionary _loggers = new(); private readonly ITestOutputHelperAccessor _accessor; diff --git a/src/Cuemon.Extensions.YamlDotNet/Formatters/PropertyTypeInspector.cs b/src/Cuemon.Extensions.YamlDotNet/Formatters/PropertyTypeInspector.cs index 3816e032..d56054c5 100644 --- a/src/Cuemon.Extensions.YamlDotNet/Formatters/PropertyTypeInspector.cs +++ b/src/Cuemon.Extensions.YamlDotNet/Formatters/PropertyTypeInspector.cs @@ -7,7 +7,7 @@ namespace Cuemon.Extensions.YamlDotNet.Formatters { - internal class PropertyTypeInspector : TypeInspectorSkeleton + internal sealed class PropertyTypeInspector : TypeInspectorSkeleton { private readonly ITypeInspector _inspector; diff --git a/src/Cuemon.Extensions.YamlDotNet/YamlConverterFactory.cs b/src/Cuemon.Extensions.YamlDotNet/YamlConverterFactory.cs index d41521cd..cc95937f 100644 --- a/src/Cuemon.Extensions.YamlDotNet/YamlConverterFactory.cs +++ b/src/Cuemon.Extensions.YamlDotNet/YamlConverterFactory.cs @@ -60,7 +60,7 @@ public static YamlConverter Create(Func predicate, Action predicate, Action writer, Func reader) { @@ -93,7 +93,7 @@ public override bool CanConvert(Type typeToConvert) } } - internal class DynamicConvertFactory : YamlConverter + internal sealed class DynamicConvertFactory : YamlConverter { internal DynamicConvertFactory(Func predicate, Action writer, Func reader) { diff --git a/src/Cuemon.Threading/AsyncForwardIterator.cs b/src/Cuemon.Threading/AsyncForwardIterator.cs index 56ecca68..cd69931f 100644 --- a/src/Cuemon.Threading/AsyncForwardIterator.cs +++ b/src/Cuemon.Threading/AsyncForwardIterator.cs @@ -3,7 +3,7 @@ namespace Cuemon.Threading { - internal class AsyncForwardIterator + internal sealed class AsyncForwardIterator { internal AsyncForwardIterator(TReader reader, Func> condition, Func provider) { @@ -31,4 +31,4 @@ public async Task ReadAsync() return false; } } -} \ No newline at end of file +} diff --git a/src/Cuemon.Threading/ForwardIterator.cs b/src/Cuemon.Threading/ForwardIterator.cs index 9539ee37..f6ce65cf 100644 --- a/src/Cuemon.Threading/ForwardIterator.cs +++ b/src/Cuemon.Threading/ForwardIterator.cs @@ -2,7 +2,7 @@ namespace Cuemon.Threading { - internal class ForwardIterator + internal sealed class ForwardIterator { internal ForwardIterator(TReader reader, Func condition, Func provider) { @@ -30,4 +30,4 @@ public bool Read() return false; } } -} \ No newline at end of file +} diff --git a/src/Cuemon.Xml/Serialization/DynamicXmlSerializable.cs b/src/Cuemon.Xml/Serialization/DynamicXmlSerializable.cs index 31ad7008..7905df38 100644 --- a/src/Cuemon.Xml/Serialization/DynamicXmlSerializable.cs +++ b/src/Cuemon.Xml/Serialization/DynamicXmlSerializable.cs @@ -26,7 +26,7 @@ public static IXmlSerializable Create(T source, Action writer, } } - internal class DynamicXmlSerializable : IXmlSerializable + internal sealed class DynamicXmlSerializable : IXmlSerializable { internal DynamicXmlSerializable(T source, Action writer, Action reader, Func schema) { @@ -74,4 +74,4 @@ public void WriteXml(XmlWriter writer) Writer(writer, Source); } } -} \ No newline at end of file +} From 4cb0396830f235328a286de080f474dbddf000b5 Mon Sep 17 00:00:00 2001 From: Michael Mortensen Date: Sat, 14 Sep 2024 23:38:14 +0200 Subject: [PATCH 14/37] :rotating_light: https://learn.microsoft.com/en-us/dotnet/fundamentals/code-analysis/quality-rules/ca1852 --- src/Cuemon.Core/Text/Parser.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Cuemon.Core/Text/Parser.cs b/src/Cuemon.Core/Text/Parser.cs index 69cbe046..098ef9bc 100644 --- a/src/Cuemon.Core/Text/Parser.cs +++ b/src/Cuemon.Core/Text/Parser.cs @@ -33,7 +33,7 @@ public bool TryParse(string input, Type targetType, out object result) } } - internal class Parser : IParser + internal sealed class Parser : IParser { private readonly Func _parser; From c55734a41e7c40032f875c52db98906cdb546eb0 Mon Sep 17 00:00:00 2001 From: Michael Mortensen Date: Sat, 14 Sep 2024 23:39:11 +0200 Subject: [PATCH 15/37] :rotating_light: https://learn.microsoft.com/en-us/dotnet/fundamentals/code-analysis/quality-rules/ca1852 --- src/Cuemon.Core/Text/Parser.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Cuemon.Core/Text/Parser.cs b/src/Cuemon.Core/Text/Parser.cs index 098ef9bc..e84961d1 100644 --- a/src/Cuemon.Core/Text/Parser.cs +++ b/src/Cuemon.Core/Text/Parser.cs @@ -53,7 +53,7 @@ public bool TryParse(string input, out TResult result) } } - internal class ConfigurableParser : IConfigurableParser where TOptions : class, IParameterObject, new() + internal sealed class ConfigurableParser : IConfigurableParser where TOptions : class, IParameterObject, new() { private readonly Func, TResult> _parser; @@ -73,7 +73,7 @@ public bool TryParse(string input, out TResult result, Action setup = } } - internal class ConfigurableParser : IConfigurableParser where TOptions : class, IParameterObject, new() + internal sealed class ConfigurableParser : IConfigurableParser where TOptions : class, IParameterObject, new() { private readonly Func, object> _parser; From 7aa665e90e6c7698255516860d557a6df5db75c1 Mon Sep 17 00:00:00 2001 From: Michael Mortensen Date: Sat, 14 Sep 2024 23:41:34 +0200 Subject: [PATCH 16/37] :rotating_light: https://learn.microsoft.com/en-us/dotnet/fundamentals/code-analysis/quality-rules/ca1858 --- src/Cuemon.Xml/Extensions/Linq/StringDecoratorExtensions.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Cuemon.Xml/Extensions/Linq/StringDecoratorExtensions.cs b/src/Cuemon.Xml/Extensions/Linq/StringDecoratorExtensions.cs index 12ae23a5..1c0c2f75 100644 --- a/src/Cuemon.Xml/Extensions/Linq/StringDecoratorExtensions.cs +++ b/src/Cuemon.Xml/Extensions/Linq/StringDecoratorExtensions.cs @@ -33,7 +33,7 @@ public static bool TryParseXElement(this IDecorator decorator, LoadOptio { result = null; if (string.IsNullOrWhiteSpace(decorator.Inner)) { return false; } - if (decorator.Inner.IndexOf("<", StringComparison.Ordinal) == 0) + if (decorator.Inner.StartsWith("<", StringComparison.Ordinal)) { try { @@ -58,4 +58,4 @@ public static bool IsXmlString(this IDecorator decorator) return TryParseXElement(decorator, out _); } } -} \ No newline at end of file +} From c6a84662bf23f198b9da596b7a3cc40047c13ed0 Mon Sep 17 00:00:00 2001 From: Michael Mortensen Date: Sat, 14 Sep 2024 23:46:58 +0200 Subject: [PATCH 17/37] :rotating_light: https://learn.microsoft.com/en-us/dotnet/fundamentals/code-analysis/quality-rules/ca1854 --- src/Cuemon.Core/Hierarchy.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Cuemon.Core/Hierarchy.cs b/src/Cuemon.Core/Hierarchy.cs index 4bdc2baa..8d8025b2 100644 --- a/src/Cuemon.Core/Hierarchy.cs +++ b/src/Cuemon.Core/Hierarchy.cs @@ -290,9 +290,9 @@ public static IHierarchy GetObjectHierarchy(object source, Action Date: Sat, 14 Sep 2024 23:49:47 +0200 Subject: [PATCH 18/37] :rotating_light: https://learn.microsoft.com/en-us/dotnet/fundamentals/code-analysis/quality-rules/ca1862 --- .../Extensions/Reflection/AssemblyDecoratorExtensions.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Cuemon.Core/Extensions/Reflection/AssemblyDecoratorExtensions.cs b/src/Cuemon.Core/Extensions/Reflection/AssemblyDecoratorExtensions.cs index 259ead91..79005d59 100644 --- a/src/Cuemon.Core/Extensions/Reflection/AssemblyDecoratorExtensions.cs +++ b/src/Cuemon.Core/Extensions/Reflection/AssemblyDecoratorExtensions.cs @@ -144,7 +144,7 @@ public static IDictionary GetManifestResources(this IDecorator extension.ToUpperInvariant() == Path.GetExtension(name)?.ToUpperInvariant()); + AddResourcesWhenExtensionPredicate(resources, resourceNames, name, decorator.Inner, (extension, matchExtension) => string.Equals(extension, Path.GetExtension(name), StringComparison.OrdinalIgnoreCase)); break; case ManifestResourceMatch.ContainsExtension: AddResourcesWhenExtensionPredicate(resources, resourceNames, name, decorator.Inner, (extension, matchExtension) => extension.IndexOf(matchExtension, StringComparison.OrdinalIgnoreCase) != -1); From db8499db51affc24b9cd8ad18fc8fcaaf80bbaa6 Mon Sep 17 00:00:00 2001 From: Michael Mortensen Date: Sun, 15 Sep 2024 00:05:07 +0200 Subject: [PATCH 19/37] :rotating_light: ca2022 --- src/Cuemon.Core/GlobalSuppressions.cs | 1 + src/Cuemon.Data.Integrity/DataIntegrityFactory.cs | 2 +- src/Cuemon.Data.Integrity/GlobalSuppressions.cs | 1 + src/Cuemon.Security.Cryptography/AesCryptor.cs | 2 +- src/Cuemon.Security.Cryptography/GlobalSuppressions.cs | 8 ++++++++ 5 files changed, 12 insertions(+), 2 deletions(-) create mode 100644 src/Cuemon.Security.Cryptography/GlobalSuppressions.cs diff --git a/src/Cuemon.Core/GlobalSuppressions.cs b/src/Cuemon.Core/GlobalSuppressions.cs index 9046b8e0..678f8c32 100644 --- a/src/Cuemon.Core/GlobalSuppressions.cs +++ b/src/Cuemon.Core/GlobalSuppressions.cs @@ -263,3 +263,4 @@ [assembly: SuppressMessage("Globalization", "CA1305:Specify IFormatProvider", Justification = "Not relevant in this context.", Scope = "member", Target = "~M:Cuemon.Runtime.Serialization.HierarchySerializer.ToString(System.Text.StringBuilder,Cuemon.IHierarchy{System.Object})")] [assembly: SuppressMessage("Globalization", "CA1304:Specify CultureInfo", Justification = "Intentionally written for only en-US support.", Scope = "member", Target = "~M:Cuemon.Reflection.MemberArgumentDecoratorExtensions.CreateException(Cuemon.IDecorator{System.Collections.Generic.Stack{System.Collections.Generic.IList{Cuemon.Reflection.MemberArgument}}},System.Boolean)~System.Exception")] [assembly: SuppressMessage("Naming", "CA1710:Identifiers should have correct suffix", Justification = "Explicit implementation.", Scope = "type", Target = "~T:Cuemon.Diagnostics.Failure")] +[assembly: SuppressMessage("Reliability", "CA2022:Avoid inexact read with 'Stream.Read'", Justification = "Byteordermark - best effort.", Scope = "member", Target = "~M:Cuemon.Text.ByteOrderMark.TryDetectEncoding(System.IO.Stream,System.Text.Encoding@)~System.Boolean")] diff --git a/src/Cuemon.Data.Integrity/DataIntegrityFactory.cs b/src/Cuemon.Data.Integrity/DataIntegrityFactory.cs index 217bd3ed..96106822 100644 --- a/src/Cuemon.Data.Integrity/DataIntegrityFactory.cs +++ b/src/Cuemon.Data.Integrity/DataIntegrityFactory.cs @@ -37,4 +37,4 @@ public static IDataIntegrity CreateIntegrity(FileInfo file, Action()); } } -} \ No newline at end of file +} diff --git a/src/Cuemon.Data.Integrity/GlobalSuppressions.cs b/src/Cuemon.Data.Integrity/GlobalSuppressions.cs index 62f20cfd..8f6c7c5f 100644 --- a/src/Cuemon.Data.Integrity/GlobalSuppressions.cs +++ b/src/Cuemon.Data.Integrity/GlobalSuppressions.cs @@ -7,3 +7,4 @@ [assembly: SuppressMessage("Major Bug", "S2259:Null pointers should not be dereferenced", Justification = "False-Positive", Scope = "member", Target = "~M:Cuemon.Data.Integrity.CacheValidator.#ctor(Cuemon.Data.Integrity.EntityInfo,System.Func{Cuemon.Security.Hash},Cuemon.Data.Integrity.EntityDataIntegrityMethod)")] [assembly: SuppressMessage("Style", "IDE0130:Namespace does not match folder structure", Justification = "Intentional as these embark on IDecorator.", Scope = "namespace", Target = "~N:Cuemon.Data.Integrity")] +[assembly: SuppressMessage("Reliability", "CA2022:Avoid inexact read with 'Stream.Read'", Justification = "Not vital in this context.", Scope = "member", Target = "~M:Cuemon.Data.Integrity.DataIntegrityFactory.CreateIntegrity(System.IO.FileInfo,System.Action{Cuemon.Data.Integrity.FileIntegrityOptions})~Cuemon.Data.Integrity.IDataIntegrity")] diff --git a/src/Cuemon.Security.Cryptography/AesCryptor.cs b/src/Cuemon.Security.Cryptography/AesCryptor.cs index 145a0e64..e60ab45a 100644 --- a/src/Cuemon.Security.Cryptography/AesCryptor.cs +++ b/src/Cuemon.Security.Cryptography/AesCryptor.cs @@ -152,4 +152,4 @@ private enum AesMode Decrypt } } -} \ No newline at end of file +} diff --git a/src/Cuemon.Security.Cryptography/GlobalSuppressions.cs b/src/Cuemon.Security.Cryptography/GlobalSuppressions.cs new file mode 100644 index 00000000..cdbcbcd1 --- /dev/null +++ b/src/Cuemon.Security.Cryptography/GlobalSuppressions.cs @@ -0,0 +1,8 @@ +// This file is used by Code Analysis to maintain SuppressMessage +// attributes that are applied to this project. +// Project-level suppressions either have no target or are given +// a specific target and scoped to a namespace, type, member, etc. + +using System.Diagnostics.CodeAnalysis; + +[assembly: SuppressMessage("Reliability", "CA2022:Avoid inexact read with 'Stream.Read'", Justification = "Worked since implementation; only method compatible with netstandard2.0.", Scope = "member", Target = "~M:Cuemon.Security.Cryptography.AesCryptor.CryptoTransformCore(System.Byte[],Cuemon.Security.Cryptography.AesCryptor.AesMode,System.Action{Cuemon.Security.Cryptography.AesCryptorOptions})~System.Byte[]")] From c38ce4723145aab68d056d954c81cba371e86868 Mon Sep 17 00:00:00 2001 From: Michael Mortensen Date: Sun, 15 Sep 2024 00:09:13 +0200 Subject: [PATCH 20/37] :rotating_light: ca2022 :bug: removed null-validation as this method uses a Try-Parse Pattern --- src/Cuemon.Core/Text/ByteOrderMark.cs | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/Cuemon.Core/Text/ByteOrderMark.cs b/src/Cuemon.Core/Text/ByteOrderMark.cs index 246dc3cc..cac80e91 100644 --- a/src/Cuemon.Core/Text/ByteOrderMark.cs +++ b/src/Cuemon.Core/Text/ByteOrderMark.cs @@ -121,8 +121,7 @@ public static bool TryDetectEncoding(byte[] input, out Encoding result) /// true if the parameter was converted successfully; otherwise, false. public static bool TryDetectEncoding(Stream value, out Encoding result) { - Validator.ThrowIfNull(value); - if (!value.CanSeek) + if (value == null || !value.CanSeek) { result = null; return false; From 018c6910db78cdfc8953bbb624f7eb3b76cca4c0 Mon Sep 17 00:00:00 2001 From: Michael Mortensen Date: Sun, 15 Sep 2024 00:18:16 +0200 Subject: [PATCH 21/37] :rotating_light: https://learn.microsoft.com/en-us/dotnet/fundamentals/code-analysis/quality-rules/ca2215 --- src/Cuemon.Extensions.Net/GlobalSuppressions.cs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/Cuemon.Extensions.Net/GlobalSuppressions.cs b/src/Cuemon.Extensions.Net/GlobalSuppressions.cs index 0f621dc7..141cc4b2 100644 --- a/src/Cuemon.Extensions.Net/GlobalSuppressions.cs +++ b/src/Cuemon.Extensions.Net/GlobalSuppressions.cs @@ -5,4 +5,5 @@ using System.Diagnostics.CodeAnalysis; -[assembly: SuppressMessage("Major Code Smell", "S3881:\"IDisposable\" should be implemented correctly", Justification = "The lifetime of this is tracked separately by ActiveHandler.", Scope = "type", Target = "~T:Cuemon.Extensions.Net.Http.TrackingHttpMessageHandler")] \ No newline at end of file +[assembly: SuppressMessage("Major Code Smell", "S3881:\"IDisposable\" should be implemented correctly", Justification = "The lifetime of this is tracked separately by ActiveHandler.", Scope = "type", Target = "~T:Cuemon.Extensions.Net.Http.TrackingHttpMessageHandler")] +[assembly: SuppressMessage("Usage", "CA2215:Dispose methods should call base class dispose", Justification = "The lifetime of this is tracked separately by ActiveHandler.", Scope = "member", Target = "~M:Cuemon.Extensions.Net.Http.TrackingHttpMessageHandler.Dispose(System.Boolean)")] From b6abe0ab521305ce4d16655f06a5b115f9b77f41 Mon Sep 17 00:00:00 2001 From: Michael Mortensen Date: Sun, 15 Sep 2024 00:20:16 +0200 Subject: [PATCH 22/37] :rotating_light: abundant exclusions primarly due to lack of support from tfm netstandard2.0 --- .editorconfig | 42 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 42 insertions(+) diff --git a/.editorconfig b/.editorconfig index 06f03f60..0765ff3c 100644 --- a/.editorconfig +++ b/.editorconfig @@ -95,3 +95,45 @@ dotnet_diagnostic.IDE0046.severity = none # https://learn.microsoft.com/en-us/dotnet/fundamentals/code-analysis/style-rules/ide0047-ide0048 [*.{cs,vb}] dotnet_diagnostic.IDE0047.severity = none + +# CA1716: Identifiers should not match keywords +# https://learn.microsoft.com/en-us/dotnet/fundamentals/code-analysis/quality-rules/ca1716 +[*.{cs,vb}] +dotnet_diagnostic.CA1716.severity = none + +# CA1720: Identifiers should not contain type names +# https://learn.microsoft.com/en-us/dotnet/fundamentals/code-analysis/quality-rules/ca1720 +[*.{cs,vb}] +dotnet_diagnostic.CA1720.severity = none + +# CA1846: Prefer AsSpan over Substring +# https://learn.microsoft.com/en-us/dotnet/fundamentals/code-analysis/quality-rules/ca1846 +# Excluded while TFMs include netstandard2.0 +[*.{cs,vb}] +dotnet_diagnostic.CA1846.severity = none + +# CA1847: Use String.Contains(char) instead of String.Contains(string) with single characters +# https://learn.microsoft.com/en-us/dotnet/fundamentals/code-analysis/quality-rules/ca1847 +# Excluded while TFMs include netstandard2.0 +[*.{cs,vb}] +dotnet_diagnostic.CA1847.severity = none + +# CA1865-CA1867: Use 'string.Method(char)' instead of 'string.Method(string)' for string with single char +# https://learn.microsoft.com/en-us/dotnet/fundamentals/code-analysis/quality-rules/ca1865-ca1867 +# Excluded while TFMs include netstandard2.0 +[*.{cs,vb}] +dotnet_diagnostic.CA1865.severity = none +dotnet_diagnostic.CA1866.severity = none +dotnet_diagnostic.CA1867.severity = none + +# CA2263: Prefer generic overload when type is known +# https://learn.microsoft.com/en-us/dotnet/fundamentals/code-analysis/quality-rules/ca2263 +# Excluded while TFMs include netstandard2.0 +[*.{cs,vb}] +dotnet_diagnostic.CA2263.severity = none + +# CA2249: Consider using String.Contains instead of String.IndexOf +# https://learn.microsoft.com/en-us/dotnet/fundamentals/code-analysis/quality-rules/ca2249 +# Excluded while TFMs include netstandard2.0 +[*.{cs,vb}] +dotnet_diagnostic.CA2249.severity = none From 4f35a831287a8299d548e63cdc9d3567d1edebb0 Mon Sep 17 00:00:00 2001 From: Michael Mortensen Date: Sun, 15 Sep 2024 00:25:04 +0200 Subject: [PATCH 23/37] :rotating_light: https://learn.microsoft.com/en-us/dotnet/fundamentals/code-analysis/quality-rules/ca5372 --- .../GlobalSuppressions.cs | 8 ++++++++ src/Cuemon.Xml/GlobalSuppressions.cs | 2 ++ 2 files changed, 10 insertions(+) create mode 100644 src/Cuemon.Extensions.Swashbuckle.AspNetCore/GlobalSuppressions.cs diff --git a/src/Cuemon.Extensions.Swashbuckle.AspNetCore/GlobalSuppressions.cs b/src/Cuemon.Extensions.Swashbuckle.AspNetCore/GlobalSuppressions.cs new file mode 100644 index 00000000..60ba87d2 --- /dev/null +++ b/src/Cuemon.Extensions.Swashbuckle.AspNetCore/GlobalSuppressions.cs @@ -0,0 +1,8 @@ +// This file is used by Code Analysis to maintain SuppressMessage +// attributes that are applied to this project. +// Project-level suppressions either have no target or are given +// a specific target and scoped to a namespace, type, member, etc. + +using System.Diagnostics.CodeAnalysis; + +[assembly: SuppressMessage("Security", "CA5372:Use XmlReader for XPathDocument constructor", Justification = "Does not apply to XML documentation files.", Scope = "member", Target = "~M:Cuemon.Extensions.Swashbuckle.AspNetCore.XPathDocumentExtensions.AddByFilename(System.Collections.Generic.IList{System.Xml.XPath.XPathDocument},System.String)~System.Collections.Generic.IList{System.Xml.XPath.XPathDocument}")] diff --git a/src/Cuemon.Xml/GlobalSuppressions.cs b/src/Cuemon.Xml/GlobalSuppressions.cs index a023f771..2929c66b 100644 --- a/src/Cuemon.Xml/GlobalSuppressions.cs +++ b/src/Cuemon.Xml/GlobalSuppressions.cs @@ -15,3 +15,5 @@ [assembly: SuppressMessage("Style", "IDE0130:Namespace does not match folder structure", Justification = "Intentional as these embark on IDecorator.", Scope = "namespace", Target = "~N:Cuemon.Xml.Linq")] [assembly: SuppressMessage("Style", "IDE0130:Namespace does not match folder structure", Justification = "Intentional as these embark on IDecorator.", Scope = "namespace", Target = "~N:Cuemon.Xml.Serialization")] [assembly: SuppressMessage("Style", "IDE0130:Namespace does not match folder structure", Justification = "Intentional as these embark on IDecorator.", Scope = "namespace", Target = "~N:Cuemon.Xml.Serialization.Converters")] +[assembly: SuppressMessage("Security", "CA5372:Use XmlReader for XPathDocument constructor", Justification = "Convenience.", Scope = "member", Target = "~M:Cuemon.Xml.XPath.XPathDocumentFactory.CreateDocument(System.Uri)~System.Xml.XPath.XPathDocument")] +[assembly: SuppressMessage("Security", "CA5372:Use XmlReader for XPathDocument constructor", Justification = "Convenience.", Scope = "member", Target = "~M:Cuemon.Xml.XPath.XPathDocumentFactory.CreateDocument(System.IO.Stream,System.Boolean)~System.Xml.XPath.XPathDocument")] From d2abe9ce6d6676c79b1031c0a83c8dea23e99781 Mon Sep 17 00:00:00 2001 From: Michael Mortensen Date: Sun, 15 Sep 2024 00:27:55 +0200 Subject: [PATCH 24/37] :rotating_light: https://learn.microsoft.com/en-us/dotnet/fundamentals/code-analysis/style-rules/ide0019 --- .../Digest/DigestAuthenticationMiddleware.cs | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/Cuemon.AspNetCore.Authentication/Digest/DigestAuthenticationMiddleware.cs b/src/Cuemon.AspNetCore.Authentication/Digest/DigestAuthenticationMiddleware.cs index 4d055348..996387f5 100644 --- a/src/Cuemon.AspNetCore.Authentication/Digest/DigestAuthenticationMiddleware.cs +++ b/src/Cuemon.AspNetCore.Authentication/Digest/DigestAuthenticationMiddleware.cs @@ -72,7 +72,6 @@ await Decorator.Enclose(context).InvokeUnauthorizedExceptionAsync(Options, princ internal static bool TryAuthenticate(HttpContext context, DigestAuthorizationHeader header, out ConditionalValue result) { var options = context.Items[nameof(DigestAuthenticationOptions)] as DigestAuthenticationOptions; - var nonceTracker = context.Items[nameof(INonceTracker)] as INonceTracker; if (options?.Authenticator == null) { result = new UnsuccessfulValue(new SecurityException($"{nameof(options.Authenticator)} was unexpectedly set to null.")); @@ -94,7 +93,7 @@ internal static bool TryAuthenticate(HttpContext context, DigestAuthorizationHea return false; } - if (nonceTracker != null) + if (context.Items[nameof(INonceTracker)] is INonceTracker nonceTracker) { var nc = Convert.ToInt32(header.NC, 16); if (nonceTracker.TryGetEntry(header.Nonce, out var previousNonce)) From 9d03acaa859f840d975e29b56730a923f1443cb0 Mon Sep 17 00:00:00 2001 From: Michael Mortensen Date: Sun, 15 Sep 2024 00:28:19 +0200 Subject: [PATCH 25/37] :rotating_light: https://learn.microsoft.com/en-us/dotnet/fundamentals/code-analysis/style-rules/ide0005?pivots=lang-csharp-vb --- src/Cuemon.Core/GlobalSuppressions.cs | 1 + 1 file changed, 1 insertion(+) diff --git a/src/Cuemon.Core/GlobalSuppressions.cs b/src/Cuemon.Core/GlobalSuppressions.cs index 678f8c32..70def55c 100644 --- a/src/Cuemon.Core/GlobalSuppressions.cs +++ b/src/Cuemon.Core/GlobalSuppressions.cs @@ -264,3 +264,4 @@ [assembly: SuppressMessage("Globalization", "CA1304:Specify CultureInfo", Justification = "Intentionally written for only en-US support.", Scope = "member", Target = "~M:Cuemon.Reflection.MemberArgumentDecoratorExtensions.CreateException(Cuemon.IDecorator{System.Collections.Generic.Stack{System.Collections.Generic.IList{Cuemon.Reflection.MemberArgument}}},System.Boolean)~System.Exception")] [assembly: SuppressMessage("Naming", "CA1710:Identifiers should have correct suffix", Justification = "Explicit implementation.", Scope = "type", Target = "~T:Cuemon.Diagnostics.Failure")] [assembly: SuppressMessage("Reliability", "CA2022:Avoid inexact read with 'Stream.Read'", Justification = "Byteordermark - best effort.", Scope = "member", Target = "~M:Cuemon.Text.ByteOrderMark.TryDetectEncoding(System.IO.Stream,System.Text.Encoding@)~System.Boolean")] +[assembly: SuppressMessage("Style", "IDE0005:Using directive is unnecessary.", Justification = "False-positive; needed for TFM netstandard2.0.")] From 1546f126d727df5805c71e31180f8eb0c4f60ee7 Mon Sep 17 00:00:00 2001 From: Michael Mortensen Date: Sun, 15 Sep 2024 00:32:30 +0200 Subject: [PATCH 26/37] :rotating_light: https://learn.microsoft.com/en-us/dotnet/fundamentals/code-analysis/style-rules/ide0025 --- src/Cuemon.Data/DataTransferRow.cs | 10 ++-------- src/Cuemon.Data/DataTransferRowCollection.cs | 10 ++-------- src/Cuemon.Data/QueryBuilder.cs | 7 ++----- 3 files changed, 6 insertions(+), 21 deletions(-) diff --git a/src/Cuemon.Data/DataTransferRow.cs b/src/Cuemon.Data/DataTransferRow.cs index 3b6cd54f..b64b9918 100644 --- a/src/Cuemon.Data/DataTransferRow.cs +++ b/src/Cuemon.Data/DataTransferRow.cs @@ -22,19 +22,13 @@ internal DataTransferRow(DataTransferRowCollection main, int rowNumber) /// The row number. public int Number { get; private set; } - private int NumberFromZero - { - get { return Number - 1; } - } + private int NumberFromZero => Number - 1; /// /// Gets the associated columns of this row. /// /// The associated columns of this row. - public DataTransferColumnCollection Columns - { - get { return Main.Columns; } - } + public DataTransferColumnCollection Columns => Main.Columns; private int GetIndexLocation(int ordinal) { diff --git a/src/Cuemon.Data/DataTransferRowCollection.cs b/src/Cuemon.Data/DataTransferRowCollection.cs index 981a712f..f2167477 100644 --- a/src/Cuemon.Data/DataTransferRowCollection.cs +++ b/src/Cuemon.Data/DataTransferRowCollection.cs @@ -54,13 +54,7 @@ private static object ChangeDbNullToNullWhenApplicable(object value) /// Gets the column names that is present in this . /// /// The column names of a table-row in a database. - public IEnumerable ColumnNames - { - get - { - return _columnNames ??= Columns.Select(column => column.Name); - } - } + public IEnumerable ColumnNames => _columnNames ??= Columns.Select(column => column.Name); private Collection DataTransferRows { get; } = new(); @@ -114,4 +108,4 @@ IEnumerator IEnumerable.GetEnumerator() return GetEnumerator(); } } -} \ No newline at end of file +} diff --git a/src/Cuemon.Data/QueryBuilder.cs b/src/Cuemon.Data/QueryBuilder.cs index 24982568..71ebd46d 100644 --- a/src/Cuemon.Data/QueryBuilder.cs +++ b/src/Cuemon.Data/QueryBuilder.cs @@ -105,10 +105,7 @@ public int ReadLimit /// The key columns to be used in the instance. public IDictionary KeyColumns { get; } - private StringBuilder Query - { - get { return _query ??= new StringBuilder(100); } - } + private StringBuilder Query => _query ??= new StringBuilder(100); #endregion #region Methods @@ -204,4 +201,4 @@ public override string ToString() } #endregion } -} \ No newline at end of file +} From e8ba633eba44c6698abc002ffe1f8e583bf5a7c8 Mon Sep 17 00:00:00 2001 From: Michael Mortensen Date: Sun, 15 Sep 2024 00:33:18 +0200 Subject: [PATCH 27/37] :rotating_light: https://learn.microsoft.com/en-us/dotnet/fundamentals/code-analysis/style-rules/ide0026 --- src/Cuemon.Data/DataTransferRow.cs | 13 ++----------- 1 file changed, 2 insertions(+), 11 deletions(-) diff --git a/src/Cuemon.Data/DataTransferRow.cs b/src/Cuemon.Data/DataTransferRow.cs index b64b9918..0ddff6a8 100644 --- a/src/Cuemon.Data/DataTransferRow.cs +++ b/src/Cuemon.Data/DataTransferRow.cs @@ -40,13 +40,7 @@ private int GetIndexLocation(int ordinal) /// /// The column from which to return the value from. /// An that contains the data of the column. - public object this[DataTransferColumn column] - { - get - { - return column == null ? null : this[column.Ordinal]; - } - } + public object this[DataTransferColumn column] => column == null ? null : this[column.Ordinal]; /// /// Gets the value of a from the with the specified . @@ -67,10 +61,7 @@ public object this[string name] /// /// The zero-based index of the column from which to return the value from. /// An that contains the data of the column. - public object this[int index] - { - get { return index < 0 ? null : Main.Data[GetIndexLocation(index)]; } - } + public object this[int index] => index < 0 ? null : Main.Data[GetIndexLocation(index)]; /// /// Gets the value of a from the with the specified . From 9594bd9f52472fd88ca076c3275b79859128e1f2 Mon Sep 17 00:00:00 2001 From: Michael Mortensen Date: Sun, 15 Sep 2024 00:39:35 +0200 Subject: [PATCH 28/37] :rotating_light: https://learn.microsoft.com/en-us/dotnet/fundamentals/code-analysis/style-rules/ide0039 --- .../NewtonsoftJsonFormatterOptions.cs | 32 ++++++++++--------- 1 file changed, 17 insertions(+), 15 deletions(-) diff --git a/src/Cuemon.Extensions.Newtonsoft.Json/Formatters/NewtonsoftJsonFormatterOptions.cs b/src/Cuemon.Extensions.Newtonsoft.Json/Formatters/NewtonsoftJsonFormatterOptions.cs index 2c6fe74f..b2683ed4 100644 --- a/src/Cuemon.Extensions.Newtonsoft.Json/Formatters/NewtonsoftJsonFormatterOptions.cs +++ b/src/Cuemon.Extensions.Newtonsoft.Json/Formatters/NewtonsoftJsonFormatterOptions.cs @@ -103,17 +103,12 @@ public NewtonsoftJsonFormatterOptions() private void JsonPropertyHandler(PropertyInfo pi, JsonProperty jp) { - Func skipPropertyType = source => - { - switch (Type.GetTypeCode(source)) - { - default: - if (Decorator.Enclose(source).HasKeyValuePairImplementation()) { return true; } - if (Decorator.Enclose(source).HasTypes(typeof(MemberInfo)) && source != typeof(Type)) { return true; } - return false; - } - }; - Func skipProperty = property => + var skipSerialization = SkipProperty(pi) || SkipPropertyType(pi.PropertyType); + jp.ShouldSerialize = _ => !skipSerialization; + jp.ShouldDeserialize = _ => !skipSerialization; + return; + + bool SkipProperty(PropertyInfo property) { return (property.PropertyType.GetTypeInfo().IsMarshalByRef || property.PropertyType.GetTypeInfo().IsSubclassOf(typeof(Delegate)) || @@ -125,11 +120,18 @@ private void JsonPropertyHandler(PropertyInfo pi, JsonProperty jp) property.Name.Equals("HResult", StringComparison.Ordinal) || property.Name.Equals("Parent", StringComparison.Ordinal) || property.Name.Equals("TargetSite", StringComparison.Ordinal)); - }; + } - var skipSerialization = skipProperty(pi) || skipPropertyType(pi.PropertyType); - jp.ShouldSerialize = _ => !skipSerialization; - jp.ShouldDeserialize = _ => !skipSerialization; + bool SkipPropertyType(Type source) + { + switch (Type.GetTypeCode(source)) + { + default: + if (Decorator.Enclose(source).HasKeyValuePairImplementation()) { return true; } + if (Decorator.Enclose(source).HasTypes(typeof(MemberInfo)) && source != typeof(Type)) { return true; } + return false; + } + } } /// From 65b15215f93edb28eb2adf8a2ffd498c1add717c Mon Sep 17 00:00:00 2001 From: Michael Mortensen Date: Sun, 15 Sep 2024 00:42:31 +0200 Subject: [PATCH 29/37] :rotating_light: https://learn.microsoft.com/en-us/dotnet/fundamentals/code-analysis/style-rules/ide0040 --- .../Basic/BasicAuthorizationHeader.cs | 2 +- .../Digest/DigestAuthorizationHeader.cs | 2 +- .../Hmac/HmacAuthorizationHeader.cs | 2 +- src/Cuemon.Core/BitStorageCapacity.cs | 4 ++-- src/Cuemon.Core/ByteStorageCapacity.cs | 4 ++-- src/Cuemon.Core/Runtime/DependencyEventArgs.cs | 4 ++-- 6 files changed, 9 insertions(+), 9 deletions(-) diff --git a/src/Cuemon.AspNetCore.Authentication/Basic/BasicAuthorizationHeader.cs b/src/Cuemon.AspNetCore.Authentication/Basic/BasicAuthorizationHeader.cs index e7ccec62..7d310de4 100644 --- a/src/Cuemon.AspNetCore.Authentication/Basic/BasicAuthorizationHeader.cs +++ b/src/Cuemon.AspNetCore.Authentication/Basic/BasicAuthorizationHeader.cs @@ -35,7 +35,7 @@ public static BasicAuthorizationHeader Create(string authorizationHeader) /// public const string Scheme = HttpAuthenticationSchemes.Basic; - BasicAuthorizationHeader() : base(Scheme) + private BasicAuthorizationHeader() : base(Scheme) { } diff --git a/src/Cuemon.AspNetCore.Authentication/Digest/DigestAuthorizationHeader.cs b/src/Cuemon.AspNetCore.Authentication/Digest/DigestAuthorizationHeader.cs index b524d13e..b5a1f581 100644 --- a/src/Cuemon.AspNetCore.Authentication/Digest/DigestAuthorizationHeader.cs +++ b/src/Cuemon.AspNetCore.Authentication/Digest/DigestAuthorizationHeader.cs @@ -35,7 +35,7 @@ public static DigestAuthorizationHeader Create(string authorizationHeader) /// public const string Scheme = HttpAuthenticationSchemes.Digest; - DigestAuthorizationHeader() : base(Scheme) + private DigestAuthorizationHeader() : base(Scheme) { } diff --git a/src/Cuemon.AspNetCore.Authentication/Hmac/HmacAuthorizationHeader.cs b/src/Cuemon.AspNetCore.Authentication/Hmac/HmacAuthorizationHeader.cs index 6f5b4f49..1adf08c9 100644 --- a/src/Cuemon.AspNetCore.Authentication/Hmac/HmacAuthorizationHeader.cs +++ b/src/Cuemon.AspNetCore.Authentication/Hmac/HmacAuthorizationHeader.cs @@ -36,7 +36,7 @@ public static HmacAuthorizationHeader Create(string authenticationScheme, string return new HmacAuthorizationHeader(authenticationScheme).Parse(authorizationHeader, setup) as HmacAuthorizationHeader; } - HmacAuthorizationHeader(string authenticationScheme) : base(authenticationScheme) + private HmacAuthorizationHeader(string authenticationScheme) : base(authenticationScheme) { } diff --git a/src/Cuemon.Core/BitStorageCapacity.cs b/src/Cuemon.Core/BitStorageCapacity.cs index de9a969b..e82eb147 100644 --- a/src/Cuemon.Core/BitStorageCapacity.cs +++ b/src/Cuemon.Core/BitStorageCapacity.cs @@ -37,8 +37,8 @@ public static BitStorageCapacity FromBits(double bits, Action /// The to convert. /// The which may be configured. - BitStorageCapacity(BitUnit unit, Action setup = null) : base(unit, setup) + private BitStorageCapacity(BitUnit unit, Action setup = null) : base(unit, setup) { } } -} \ No newline at end of file +} diff --git a/src/Cuemon.Core/ByteStorageCapacity.cs b/src/Cuemon.Core/ByteStorageCapacity.cs index aa0f817b..98c55844 100644 --- a/src/Cuemon.Core/ByteStorageCapacity.cs +++ b/src/Cuemon.Core/ByteStorageCapacity.cs @@ -37,8 +37,8 @@ public static ByteStorageCapacity FromBytes(double bytes, Action /// The to convert. /// The which may be configured. - ByteStorageCapacity(ByteUnit unit, Action setup = null) : base(unit, setup) + private ByteStorageCapacity(ByteUnit unit, Action setup = null) : base(unit, setup) { } } -} \ No newline at end of file +} diff --git a/src/Cuemon.Core/Runtime/DependencyEventArgs.cs b/src/Cuemon.Core/Runtime/DependencyEventArgs.cs index 6263d208..5da99bf0 100644 --- a/src/Cuemon.Core/Runtime/DependencyEventArgs.cs +++ b/src/Cuemon.Core/Runtime/DependencyEventArgs.cs @@ -7,7 +7,7 @@ namespace Cuemon.Runtime /// public class DependencyEventArgs : EventArgs { - DependencyEventArgs() + private DependencyEventArgs() { } @@ -31,4 +31,4 @@ public DependencyEventArgs(DateTime utcLastModified) /// public new static readonly DependencyEventArgs Empty = new(); } -} \ No newline at end of file +} From ff21403ab5b40fc98357cfefadeef6dd8066bc20 Mon Sep 17 00:00:00 2001 From: Michael Mortensen Date: Sun, 15 Sep 2024 00:44:40 +0200 Subject: [PATCH 30/37] :rotating_light: https://learn.microsoft.com/en-us/dotnet/fundamentals/code-analysis/style-rules/ide0055 --- src/Cuemon.Core/Resilience/TransientFaultEvidence.cs | 6 +++--- src/Cuemon.Core/Security/FowlerNollVo1024.cs | 6 +++--- src/Cuemon.Core/Security/FowlerNollVo128.cs | 4 ++-- src/Cuemon.Core/Security/FowlerNollVo256.cs | 6 +++--- src/Cuemon.Core/Security/FowlerNollVo32.cs | 6 +++--- src/Cuemon.Core/Security/FowlerNollVo512.cs | 6 +++--- src/Cuemon.Core/Security/FowlerNollVo64.cs | 4 ++-- .../JDataResultExtensions.cs | 4 ++-- .../XunitTestLoggerProvider.cs | 2 +- .../AspNetCoreHostTestTest.cs | 2 +- 10 files changed, 23 insertions(+), 23 deletions(-) diff --git a/src/Cuemon.Core/Resilience/TransientFaultEvidence.cs b/src/Cuemon.Core/Resilience/TransientFaultEvidence.cs index 2b50a76a..fc0ad3a8 100644 --- a/src/Cuemon.Core/Resilience/TransientFaultEvidence.cs +++ b/src/Cuemon.Core/Resilience/TransientFaultEvidence.cs @@ -92,9 +92,9 @@ public virtual bool Equals(TransientFaultEvidence other) { if (other is null) { return false; } if (ReferenceEquals(this, other)) { return true; } - return Attempts == other.Attempts && - RecoveryWaitTime.Equals(other.RecoveryWaitTime) && - TotalRecoveryWaitTime.Equals(other.TotalRecoveryWaitTime) && + return Attempts == other.Attempts && + RecoveryWaitTime.Equals(other.RecoveryWaitTime) && + TotalRecoveryWaitTime.Equals(other.TotalRecoveryWaitTime) && Latency.Equals(other.Latency) && Descriptor.ToString().Equals(other.Descriptor.ToString(), StringComparison.Ordinal); } diff --git a/src/Cuemon.Core/Security/FowlerNollVo1024.cs b/src/Cuemon.Core/Security/FowlerNollVo1024.cs index b8f0489f..09a37b9d 100644 --- a/src/Cuemon.Core/Security/FowlerNollVo1024.cs +++ b/src/Cuemon.Core/Security/FowlerNollVo1024.cs @@ -15,9 +15,9 @@ public sealed class FowlerNollVo1024 : FowlerNollVoHash /// Initializes a new instance of the class. /// /// The which may be configured. - public FowlerNollVo1024(Action setup = null) : base(1024, - BigInteger.Parse("5016456510113118655434598811035278955030765345404790744303017523831112055108147451509157692220295382716162651878526895249385292291816524375083746691371804094271873160484737966720260389217684476157468082573", CultureInfo.InvariantCulture), - BigInteger.Parse("14197795064947621068722070641403218320880622795441933960878474914617582723252296732303717722150864096521202355549365628174669108571814760471015076148029755969804077320157692458563003215304957150157403644460363550505412711285966361610267868082893823963790439336411086884584107735010676915", CultureInfo.InvariantCulture), + public FowlerNollVo1024(Action setup = null) : base(1024, + BigInteger.Parse("5016456510113118655434598811035278955030765345404790744303017523831112055108147451509157692220295382716162651878526895249385292291816524375083746691371804094271873160484737966720260389217684476157468082573", CultureInfo.InvariantCulture), + BigInteger.Parse("14197795064947621068722070641403218320880622795441933960878474914617582723252296732303717722150864096521202355549365628174669108571814760471015076148029755969804077320157692458563003215304957150157403644460363550505412711285966361610267868082893823963790439336411086884584107735010676915", CultureInfo.InvariantCulture), setup) { } diff --git a/src/Cuemon.Core/Security/FowlerNollVo128.cs b/src/Cuemon.Core/Security/FowlerNollVo128.cs index a9df3291..7102a51c 100644 --- a/src/Cuemon.Core/Security/FowlerNollVo128.cs +++ b/src/Cuemon.Core/Security/FowlerNollVo128.cs @@ -15,9 +15,9 @@ public sealed class FowlerNollVo128 : FowlerNollVoHash /// Initializes a new instance of the class. /// /// The which may be configured. - public FowlerNollVo128(Action setup = null) : base(128, + public FowlerNollVo128(Action setup = null) : base(128, BigInteger.Parse("309485009821345068724781371", CultureInfo.InvariantCulture), - BigInteger.Parse("144066263297769815596495629667062367629", CultureInfo.InvariantCulture), + BigInteger.Parse("144066263297769815596495629667062367629", CultureInfo.InvariantCulture), setup) { } diff --git a/src/Cuemon.Core/Security/FowlerNollVo256.cs b/src/Cuemon.Core/Security/FowlerNollVo256.cs index 6ce0e529..fbd114ea 100644 --- a/src/Cuemon.Core/Security/FowlerNollVo256.cs +++ b/src/Cuemon.Core/Security/FowlerNollVo256.cs @@ -15,9 +15,9 @@ public sealed class FowlerNollVo256 : FowlerNollVoHash /// Initializes a new instance of the class. /// /// The which may be configured. - public FowlerNollVo256(Action setup = null) : base(256, - BigInteger.Parse("374144419156711147060143317175368453031918731002211", CultureInfo.InvariantCulture), - BigInteger.Parse("100029257958052580907070968620625704837092796014241193945225284501741471925557", CultureInfo.InvariantCulture), + public FowlerNollVo256(Action setup = null) : base(256, + BigInteger.Parse("374144419156711147060143317175368453031918731002211", CultureInfo.InvariantCulture), + BigInteger.Parse("100029257958052580907070968620625704837092796014241193945225284501741471925557", CultureInfo.InvariantCulture), setup) { } diff --git a/src/Cuemon.Core/Security/FowlerNollVo32.cs b/src/Cuemon.Core/Security/FowlerNollVo32.cs index 4ce578fd..622eecfe 100644 --- a/src/Cuemon.Core/Security/FowlerNollVo32.cs +++ b/src/Cuemon.Core/Security/FowlerNollVo32.cs @@ -15,9 +15,9 @@ public sealed class FowlerNollVo32 : FowlerNollVoHash /// Initializes a new instance of the class. /// /// The which may be configured. - public FowlerNollVo32(Action setup = null) : base(32, - BigInteger.Parse("16777619", CultureInfo.InvariantCulture), - BigInteger.Parse("2166136261", CultureInfo.InvariantCulture), + public FowlerNollVo32(Action setup = null) : base(32, + BigInteger.Parse("16777619", CultureInfo.InvariantCulture), + BigInteger.Parse("2166136261", CultureInfo.InvariantCulture), setup) { } diff --git a/src/Cuemon.Core/Security/FowlerNollVo512.cs b/src/Cuemon.Core/Security/FowlerNollVo512.cs index 4d93cc19..36cc043f 100644 --- a/src/Cuemon.Core/Security/FowlerNollVo512.cs +++ b/src/Cuemon.Core/Security/FowlerNollVo512.cs @@ -15,9 +15,9 @@ public sealed class FowlerNollVo512 : FowlerNollVoHash /// Initializes a new instance of the class. /// /// The which may be configured. - public FowlerNollVo512(Action setup = null) : base(512, - BigInteger.Parse("35835915874844867368919076489095108449946327955754392558399825615420669938882575126094039892345713852759", CultureInfo.InvariantCulture), - BigInteger.Parse("9659303129496669498009435400716310466090418745672637896108374329434462657994582932197716438449813051892206539805784495328239340083876191928701583869517785", CultureInfo.InvariantCulture), + public FowlerNollVo512(Action setup = null) : base(512, + BigInteger.Parse("35835915874844867368919076489095108449946327955754392558399825615420669938882575126094039892345713852759", CultureInfo.InvariantCulture), + BigInteger.Parse("9659303129496669498009435400716310466090418745672637896108374329434462657994582932197716438449813051892206539805784495328239340083876191928701583869517785", CultureInfo.InvariantCulture), setup) { } diff --git a/src/Cuemon.Core/Security/FowlerNollVo64.cs b/src/Cuemon.Core/Security/FowlerNollVo64.cs index 47a5a4ae..f29fa1d1 100644 --- a/src/Cuemon.Core/Security/FowlerNollVo64.cs +++ b/src/Cuemon.Core/Security/FowlerNollVo64.cs @@ -16,8 +16,8 @@ public sealed class FowlerNollVo64 : FowlerNollVoHash /// /// The which may be configured. public FowlerNollVo64(Action setup = null) : base(64, - BigInteger.Parse("1099511628211", CultureInfo.InvariantCulture), - BigInteger.Parse("14695981039346656037", CultureInfo.InvariantCulture), + BigInteger.Parse("1099511628211", CultureInfo.InvariantCulture), + BigInteger.Parse("14695981039346656037", CultureInfo.InvariantCulture), setup) { } diff --git a/src/Cuemon.Extensions.Newtonsoft.Json/JDataResultExtensions.cs b/src/Cuemon.Extensions.Newtonsoft.Json/JDataResultExtensions.cs index 7cbdf3f8..29d54b37 100644 --- a/src/Cuemon.Extensions.Newtonsoft.Json/JDataResultExtensions.cs +++ b/src/Cuemon.Extensions.Newtonsoft.Json/JDataResultExtensions.cs @@ -88,8 +88,8 @@ public static void ExtractArrayValues(this IEnumerable source, stri private static bool HasMatchWithAsterisk(string s, string path) { - return s.EndsWith("*", StringComparison.Ordinal) && - path.Contains('.') && + return s.EndsWith("*", StringComparison.Ordinal) && + path.Contains('.') && s.Remove(s.LastIndexOf('.')).Equals(path.Remove(path.LastIndexOf('.')), StringComparison.Ordinal); } } diff --git a/src/Cuemon.Extensions.Xunit.Hosting/XunitTestLoggerProvider.cs b/src/Cuemon.Extensions.Xunit.Hosting/XunitTestLoggerProvider.cs index ebaa6273..71407c2d 100644 --- a/src/Cuemon.Extensions.Xunit.Hosting/XunitTestLoggerProvider.cs +++ b/src/Cuemon.Extensions.Xunit.Hosting/XunitTestLoggerProvider.cs @@ -22,7 +22,7 @@ public XunitTestLoggerProvider(ITestOutputHelperAccessor accessor) public ILogger CreateLogger(string categoryName) { - return _loggers.GetOrAdd(categoryName, _ => _accessor != null + return _loggers.GetOrAdd(categoryName, _ => _accessor != null ? new XunitTestLogger(_accessor) : new XunitTestLogger(_output)); } diff --git a/test/Cuemon.Extensions.Xunit.Hosting.AspNetCore.Tests/AspNetCoreHostTestTest.cs b/test/Cuemon.Extensions.Xunit.Hosting.AspNetCore.Tests/AspNetCoreHostTestTest.cs index 50c8f8e1..bc9f3010 100644 --- a/test/Cuemon.Extensions.Xunit.Hosting.AspNetCore.Tests/AspNetCoreHostTestTest.cs +++ b/test/Cuemon.Extensions.Xunit.Hosting.AspNetCore.Tests/AspNetCoreHostTestTest.cs @@ -22,7 +22,7 @@ public AspNetCoreHostTestTest(AspNetCoreHostFixture hostFixture, ITestOutputHelp { _pipeline = hostFixture.Application; _provider = hostFixture.ServiceProvider; - + _provider.GetRequiredService().TestOutput = output; } From 33536e074364b8d3baf6ae4cbc420533183bb608 Mon Sep 17 00:00:00 2001 From: Michael Mortensen Date: Sun, 15 Sep 2024 00:46:51 +0200 Subject: [PATCH 31/37] :rotating_light: consious exclusions --- .editorconfig | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/.editorconfig b/.editorconfig index 0765ff3c..596c823a 100644 --- a/.editorconfig +++ b/.editorconfig @@ -137,3 +137,19 @@ dotnet_diagnostic.CA2263.severity = none # Excluded while TFMs include netstandard2.0 [*.{cs,vb}] dotnet_diagnostic.CA2249.severity = none + +# IDE0022: Use expression body for methods +# https://learn.microsoft.com/en-us/dotnet/fundamentals/code-analysis/style-rules/ide0022 +[*.{cs,vb}] +dotnet_diagnostic.IDE0022.severity = none + +# IDE0032: Use auto-property +# https://learn.microsoft.com/en-us/dotnet/fundamentals/code-analysis/style-rules/ide0032 +[*.{cs,vb}] +dotnet_diagnostic.IDE0032.severity = none + +# Order modifiers +# https://learn.microsoft.com/en-us/dotnet/fundamentals/code-analysis/style-rules/ide0036 +# Excluded becuase of inconsistency with other analyzers +[*.{cs,vb}] +dotnet_diagnostic.IDE0036.severity = none From 9f711cdda99f1ac7f07e38955378adea63ee5ce7 Mon Sep 17 00:00:00 2001 From: Michael Mortensen Date: Sun, 15 Sep 2024 00:49:16 +0200 Subject: [PATCH 32/37] :rotating_light: https://learn.microsoft.com/en-us/dotnet/fundamentals/code-analysis/style-rules/ide0060 --- .../DynamicContractResolver.cs | 3 +-- .../WebHostTestFactory.cs | 2 +- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/src/Cuemon.Extensions.Newtonsoft.Json/DynamicContractResolver.cs b/src/Cuemon.Extensions.Newtonsoft.Json/DynamicContractResolver.cs index eaf87076..27749646 100644 --- a/src/Cuemon.Extensions.Newtonsoft.Json/DynamicContractResolver.cs +++ b/src/Cuemon.Extensions.Newtonsoft.Json/DynamicContractResolver.cs @@ -15,10 +15,9 @@ public static class DynamicContractResolver /// Creates the specified resolver. /// /// The type that inherits from . - /// The instance of an implementation. /// The array of delegates that will handle custom rules of a . /// An implementation of . - public static IContractResolver Create(T resolver, params Action[] jsonPropertyHandlers) where T : IContractResolver + public static IContractResolver Create(params Action[] jsonPropertyHandlers) where T : IContractResolver { switch (typeof(T).Name) { diff --git a/src/Cuemon.Extensions.Xunit.Hosting.AspNetCore/WebHostTestFactory.cs b/src/Cuemon.Extensions.Xunit.Hosting.AspNetCore/WebHostTestFactory.cs index 6d449858..3a0705d0 100644 --- a/src/Cuemon.Extensions.Xunit.Hosting.AspNetCore/WebHostTestFactory.cs +++ b/src/Cuemon.Extensions.Xunit.Hosting.AspNetCore/WebHostTestFactory.cs @@ -63,7 +63,7 @@ public static async Task RunAsync(Action RunWithHostBuilderContextAsync(Action serviceSetup = null, Action pipelineSetup = null, Action hostSetup = null, Func> responseFactory = null) { using var client = CreateWithHostBuilderContext(serviceSetup, pipelineSetup, hostSetup).Host.GetTestClient(); - return await client.ToHttpResponseMessageAsync().ConfigureAwait(false); + return await client.ToHttpResponseMessageAsync(responseFactory).ConfigureAwait(false); } } } From 261bf443c7d115d9674df5e33e09cadcf37e0f06 Mon Sep 17 00:00:00 2001 From: Michael Mortensen Date: Sun, 15 Sep 2024 00:57:03 +0200 Subject: [PATCH 33/37] :alembic: consequence changes of 9f711cdda99 --- .../DynamicContractResolver.cs | 2 ++ .../Formatters/NewtonsoftJsonFormatterOptions.cs | 5 +---- 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/src/Cuemon.Extensions.Newtonsoft.Json/DynamicContractResolver.cs b/src/Cuemon.Extensions.Newtonsoft.Json/DynamicContractResolver.cs index 27749646..80edcf24 100644 --- a/src/Cuemon.Extensions.Newtonsoft.Json/DynamicContractResolver.cs +++ b/src/Cuemon.Extensions.Newtonsoft.Json/DynamicContractResolver.cs @@ -34,6 +34,7 @@ internal sealed class DynamicDefaultContractResolver : DefaultContractResolver internal DynamicDefaultContractResolver(IEnumerable> jsonPropertyHandlers) { JsonPropertyHandlers = jsonPropertyHandlers; + IgnoreSerializableInterface = true; } private IEnumerable> JsonPropertyHandlers { get; set; } @@ -54,6 +55,7 @@ internal sealed class DynamicCamelCasePropertyNamesContractResolver : CamelCaseP internal DynamicCamelCasePropertyNamesContractResolver(IEnumerable> jsonPropertyHandlers) { JsonPropertyHandlers = jsonPropertyHandlers; + IgnoreSerializableInterface = true; } private IEnumerable> JsonPropertyHandlers { get; set; } diff --git a/src/Cuemon.Extensions.Newtonsoft.Json/Formatters/NewtonsoftJsonFormatterOptions.cs b/src/Cuemon.Extensions.Newtonsoft.Json/Formatters/NewtonsoftJsonFormatterOptions.cs index b2683ed4..a8aedec4 100644 --- a/src/Cuemon.Extensions.Newtonsoft.Json/Formatters/NewtonsoftJsonFormatterOptions.cs +++ b/src/Cuemon.Extensions.Newtonsoft.Json/Formatters/NewtonsoftJsonFormatterOptions.cs @@ -86,10 +86,7 @@ public NewtonsoftJsonFormatterOptions() DateFormatHandling = DateFormatHandling.IsoDateFormat, DateFormatString = "O", DateTimeZoneHandling = DateTimeZoneHandling.RoundtripKind, - ContractResolver = DynamicContractResolver.Create(new CamelCasePropertyNamesContractResolver() - { - IgnoreSerializableInterface = true - }, JsonPropertyHandler) + ContractResolver = DynamicContractResolver.Create(JsonPropertyHandler) }; DefaultConverters?.Invoke(Settings.Converters); SensitivityDetails = FaultSensitivityDetails.None; From 2a17ebb4546471f0fee28e284985ccb50ec804f7 Mon Sep 17 00:00:00 2001 From: Michael Mortensen Date: Sun, 15 Sep 2024 01:04:23 +0200 Subject: [PATCH 34/37] :rotating_light: https://learn.microsoft.com/en-us/dotnet/fundamentals/code-analysis/style-rules/ide0076 --- .../GlobalSuppressions.cs | 8 -------- src/Cuemon.Extensions.Core/GlobalSuppressions.cs | 2 -- src/Cuemon.Extensions.YamlDotNet/GlobalSuppressions.cs | 1 - src/Cuemon.IO/GlobalSuppressions.cs | 1 + 4 files changed, 1 insertion(+), 11 deletions(-) delete mode 100644 src/Cuemon.Extensions.AspNetCore.Mvc.Formatters.Xml/GlobalSuppressions.cs diff --git a/src/Cuemon.Extensions.AspNetCore.Mvc.Formatters.Xml/GlobalSuppressions.cs b/src/Cuemon.Extensions.AspNetCore.Mvc.Formatters.Xml/GlobalSuppressions.cs deleted file mode 100644 index 7e95c24b..00000000 --- a/src/Cuemon.Extensions.AspNetCore.Mvc.Formatters.Xml/GlobalSuppressions.cs +++ /dev/null @@ -1,8 +0,0 @@ -// This file is used by Code Analysis to maintain SuppressMessage -// attributes that are applied to this project. -// Project-level suppressions either have no target or are given -// a specific target and scoped to a namespace, type, member, etc. - -using System.Diagnostics.CodeAnalysis; - -[assembly: SuppressMessage("Critical Code Smell", "S3776:Cognitive Complexity of methods should not be too high", Justification = "Clear enough; XML Converter.", Scope = "member", Target = "~M:Cuemon.Extensions.AspNetCore.Mvc.Formatters.Xml.Converters.XmlConverterExtensions.AddHttpExceptionDescriptorConverter(System.Collections.Generic.IList{Cuemon.Xml.Serialization.Converters.XmlConverter},System.Action{Cuemon.Diagnostics.ExceptionDescriptorOptions})~System.Collections.Generic.IList{Cuemon.Xml.Serialization.Converters.XmlConverter}")] diff --git a/src/Cuemon.Extensions.Core/GlobalSuppressions.cs b/src/Cuemon.Extensions.Core/GlobalSuppressions.cs index a3b67f04..b3103682 100644 --- a/src/Cuemon.Extensions.Core/GlobalSuppressions.cs +++ b/src/Cuemon.Extensions.Core/GlobalSuppressions.cs @@ -9,5 +9,3 @@ [assembly: SuppressMessage("Usage", "CA2249:Consider using 'string.Contains' instead of 'string.IndexOf'", Justification = "False-Positive. Contains does not support comparison rules in NET Standard 2.", Scope = "member", Target = "~M:Cuemon.Extensions.StringExtensions.ContainsAny(System.String,System.String,System.StringComparison)~System.Boolean")] [assembly: SuppressMessage("Minor Code Smell", "S3267:Loops should be simplified with \"LINQ\" expressions", Justification = "False-positive.", Scope = "member", Target = "~M:Cuemon.Extensions.StringExtensions.JsUnescape(System.String)~System.String")] [assembly: SuppressMessage("Style", "IDE0220:Add explicit cast", Justification = "False-Positive", Scope = "member", Target = "~M:Cuemon.Extensions.StringExtensions.JsUnescape(System.String)~System.String")] -[assembly: SuppressMessage("Major Bug", "S3343:Caller information parameters should come at the end of the parameter list", Justification = "For consistency (and to align with Microsoft recent guard improvements), paramName should always be the 2nd parameter (when applicable) OR paramName and message goes next to each other.", Scope = "member", Target = "~M:Cuemon.Extensions.ValidatorExtensions.ContainsReservedKeyword(Cuemon.Validator,System.String,System.Collections.Generic.IEnumerable{System.String},System.Collections.Generic.IEqualityComparer{System.String},System.String,System.String)")] -[assembly: SuppressMessage("Major Bug", "S3343:Caller information parameters should come at the end of the parameter list", Justification = "For consistency (and to align with Microsoft recent guard improvements), paramName should always be the 2nd parameter (when applicable) OR paramName and message goes next to each other.", Scope = "member", Target = "~M:Cuemon.Extensions.ValidatorExtensions.ContainsReservedKeyword(Cuemon.Validator,System.String,System.Collections.Generic.IEnumerable{System.String},System.String,System.String)")] diff --git a/src/Cuemon.Extensions.YamlDotNet/GlobalSuppressions.cs b/src/Cuemon.Extensions.YamlDotNet/GlobalSuppressions.cs index 9c3c80c7..a65b392f 100644 --- a/src/Cuemon.Extensions.YamlDotNet/GlobalSuppressions.cs +++ b/src/Cuemon.Extensions.YamlDotNet/GlobalSuppressions.cs @@ -7,4 +7,3 @@ [assembly: SuppressMessage("Major Code Smell", "S3011:Reflection should not be used to increase accessibility of classes, methods, or fields", Justification = "By design.", Scope = "member", Target = "~M:Cuemon.Extensions.YamlDotNet.Formatters.YamlFormatter.Serialize(System.Object,System.Type)~System.IO.Stream")] [assembly: SuppressMessage("Major Code Smell", "S3011:Reflection should not be used to increase accessibility of classes, methods, or fields", Justification = "By design.", Scope = "member", Target = "~M:Cuemon.Extensions.YamlDotNet.Formatters.YamlFormatter.Deserialize(System.IO.Stream,System.Type)~System.Object")] -[assembly: SuppressMessage("Major Code Smell", "S3011:Reflection should not be used to increase accessibility of classes, methods, or fields", Justification = "By design.", Scope = "member", Target = "~M:Cuemon.Extensions.YamlDotNet.Formatters.YamlFormatter.UseBuilder~YamlDotNet.Serialization.SerializerBuilder")] diff --git a/src/Cuemon.IO/GlobalSuppressions.cs b/src/Cuemon.IO/GlobalSuppressions.cs index 48f2875b..64c2214d 100644 --- a/src/Cuemon.IO/GlobalSuppressions.cs +++ b/src/Cuemon.IO/GlobalSuppressions.cs @@ -10,3 +10,4 @@ [assembly: SuppressMessage("Major Code Smell", "S2436:Types and methods should not have too many generic parameters", Justification = "By design; allow up to a max. of 5 generic parameters.", Scope = "member", Target = "~M:Cuemon.IO.StreamFactory.Create``4(System.Action{System.Buffers.IBufferWriter{System.Byte},``0,``1,``2,``3},``0,``1,``2,``3,System.Action{Cuemon.IO.BufferWriterOptions})~System.IO.Stream")] [assembly: SuppressMessage("Major Code Smell", "S2436:Types and methods should not have too many generic parameters", Justification = "By design; allow up to a max. of 5 generic parameters.", Scope = "member", Target = "~M:Cuemon.IO.StreamFactory.Create``5(System.Action{System.Buffers.IBufferWriter{System.Byte},``0,``1,``2,``3,``4},``0,``1,``2,``3,``4,System.Action{Cuemon.IO.BufferWriterOptions})~System.IO.Stream")] [assembly: SuppressMessage("Style", "IDE0130:Namespace does not match folder structure", Justification = "Intentional as these embark on IDecorator.", Scope = "namespace", Target = "~N:Cuemon.IO")] +[assembly: SuppressMessage("CodeQuality", "IDE0076:Invalid global 'SuppressMessageAttribute'", Justification = "Only applicable for TFM netstandard2.0.")] From 6ca25300a153b2b483d60dabc1226acfe9e611c0 Mon Sep 17 00:00:00 2001 From: Michael Mortensen Date: Sun, 15 Sep 2024 01:05:06 +0200 Subject: [PATCH 35/37] :rotating_light: https://learn.microsoft.com/en-us/dotnet/fundamentals/code-analysis/style-rules/ide0200 --- src/Cuemon.Data/DsvDataReader.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Cuemon.Data/DsvDataReader.cs b/src/Cuemon.Data/DsvDataReader.cs index 8ba9f924..6db0db38 100644 --- a/src/Cuemon.Data/DsvDataReader.cs +++ b/src/Cuemon.Data/DsvDataReader.cs @@ -135,7 +135,7 @@ public override bool Read() /// public Task ReadAsync() { - return ReadAllLinesAsync(async () => await Reader.ReadLineAsync().ConfigureAwait(false)); + return ReadAllLinesAsync(Reader.ReadLineAsync); } private async Task ReadAllLinesAsync(Func> readLineAsyncCallback) From 43d87b724d28507d1ad7af99a2a0d33e9b5db0ca Mon Sep 17 00:00:00 2001 From: Michael Mortensen Date: Sun, 15 Sep 2024 01:18:34 +0200 Subject: [PATCH 36/37] :rotating_light: https://sonarcloud.io/organizations/geekle/rules?open=csharpsquid%3AS1172&rule_key=csharpsquid%3AS1172 --- src/Cuemon.Extensions.Newtonsoft.Json/GlobalSuppressions.cs | 1 + src/Cuemon.Extensions.Text.Json/GlobalSuppressions.cs | 1 + src/Cuemon.Xml/GlobalSuppressions.cs | 1 + 3 files changed, 3 insertions(+) diff --git a/src/Cuemon.Extensions.Newtonsoft.Json/GlobalSuppressions.cs b/src/Cuemon.Extensions.Newtonsoft.Json/GlobalSuppressions.cs index 6393cb97..56e7c942 100644 --- a/src/Cuemon.Extensions.Newtonsoft.Json/GlobalSuppressions.cs +++ b/src/Cuemon.Extensions.Newtonsoft.Json/GlobalSuppressions.cs @@ -10,3 +10,4 @@ [assembly: SuppressMessage("CodeQuality", "IDE0052:Remove unread private members", Justification = "Left for debugging purposes.", Scope = "member", Target = "~P:Cuemon.Extensions.Newtonsoft.Json.DynamicJsonConverterCore.ObjectType")] [assembly: SuppressMessage("Major Bug", "S3343:Caller information parameters should come at the end of the parameter list", Justification = "For consistency (and to align with Microsoft recent guard improvements), paramName should always be the 2nd parameter (when applicable) OR paramName and message goes next to each other.", Scope = "member", Target = "~M:Cuemon.Extensions.Newtonsoft.Json.ValidatorExtensions.InvalidJsonDocument(Cuemon.Validator,Newtonsoft.Json.JsonReader@,System.String,System.String)")] [assembly: SuppressMessage("Major Bug", "S3343:Caller information parameters should come at the end of the parameter list", Justification = "For consistency (and to align with Microsoft recent guard improvements), paramName should always be the 2nd parameter (when applicable) OR paramName and message goes next to each other.", Scope = "member", Target = "~M:Cuemon.Extensions.Newtonsoft.Json.ValidatorExtensions.InvalidJsonDocument(Cuemon.Validator,System.String,System.String,System.String)")] +[assembly: SuppressMessage("Major Code Smell", "S1172:Unused method parameters should be removed", Justification = "False-positive; value is conditionally used.", Scope = "member", Target = "~M:Cuemon.Extensions.Newtonsoft.Json.Converters.ExceptionConverter.ParseJsonReader(Newtonsoft.Json.JsonReader,System.Type)~System.Collections.Generic.Stack{System.Collections.Generic.IList{Cuemon.Reflection.MemberArgument}}")] diff --git a/src/Cuemon.Extensions.Text.Json/GlobalSuppressions.cs b/src/Cuemon.Extensions.Text.Json/GlobalSuppressions.cs index cbabe682..5369adb2 100644 --- a/src/Cuemon.Extensions.Text.Json/GlobalSuppressions.cs +++ b/src/Cuemon.Extensions.Text.Json/GlobalSuppressions.cs @@ -8,3 +8,4 @@ [assembly: SuppressMessage("Critical Code Smell", "S3776:Cognitive Complexity of methods should not be too high", Justification = "Transitioned legacy code ;-)", Scope = "member", Target = "~M:Cuemon.Extensions.Text.Json.JsonReaderExtensions.ToHierarchy(System.Text.Json.Utf8JsonReader)~Cuemon.IHierarchy{Cuemon.DataPair}")] [assembly: SuppressMessage("Major Code Smell", "S907:\"goto\" statement should not be used", Justification = "Transitioned legacy code ;-)", Scope = "member", Target = "~M:Cuemon.Extensions.Text.Json.JsonReaderExtensions.ToHierarchy(System.Text.Json.Utf8JsonReader)~Cuemon.IHierarchy{Cuemon.DataPair}")] [assembly: SuppressMessage("CodeQuality", "IDE0052:Remove unread private members", Justification = "False-positive; .NET 7 reads this value.", Scope = "member", Target = "~P:Cuemon.Extensions.Text.Json.Converters.FlagsEnumConverter.TypeToConvert")] +[assembly: SuppressMessage("Major Code Smell", "S1172:Unused method parameters should be removed", Justification = "False-positive; value is conditionally used.", Scope = "member", Target = "~M:Cuemon.Extensions.Text.Json.Converters.ExceptionConverter.ParseJsonReader(System.Text.Json.Utf8JsonReader@,System.Type)~System.Collections.Generic.Stack{System.Collections.Generic.IList{Cuemon.Reflection.MemberArgument}}")] diff --git a/src/Cuemon.Xml/GlobalSuppressions.cs b/src/Cuemon.Xml/GlobalSuppressions.cs index 2929c66b..1e1230d1 100644 --- a/src/Cuemon.Xml/GlobalSuppressions.cs +++ b/src/Cuemon.Xml/GlobalSuppressions.cs @@ -17,3 +17,4 @@ [assembly: SuppressMessage("Style", "IDE0130:Namespace does not match folder structure", Justification = "Intentional as these embark on IDecorator.", Scope = "namespace", Target = "~N:Cuemon.Xml.Serialization.Converters")] [assembly: SuppressMessage("Security", "CA5372:Use XmlReader for XPathDocument constructor", Justification = "Convenience.", Scope = "member", Target = "~M:Cuemon.Xml.XPath.XPathDocumentFactory.CreateDocument(System.Uri)~System.Xml.XPath.XPathDocument")] [assembly: SuppressMessage("Security", "CA5372:Use XmlReader for XPathDocument constructor", Justification = "Convenience.", Scope = "member", Target = "~M:Cuemon.Xml.XPath.XPathDocumentFactory.CreateDocument(System.IO.Stream,System.Boolean)~System.Xml.XPath.XPathDocument")] +[assembly: SuppressMessage("Major Code Smell", "S1172:Unused method parameters should be removed", Justification = "False-positive; value is conditionally used.", Scope = "member", Target = "~M:Cuemon.Xml.Serialization.Converters.ExceptionConverter.ParseXmlReader(System.Xml.XmlReader,System.Type)~System.Collections.Generic.Stack{System.Collections.Generic.IList{Cuemon.Reflection.MemberArgument}}")] From c3dba38ed623a71ab386e05d5a511ee1a3d8f3f4 Mon Sep 17 00:00:00 2001 From: Michael Mortensen Date: Sun, 15 Sep 2024 01:19:45 +0200 Subject: [PATCH 37/37] :rotating_light: ignore IDE0330 while supported TFMs are less than net9.0 --- .editorconfig | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/.editorconfig b/.editorconfig index 596c823a..9a5251c9 100644 --- a/.editorconfig +++ b/.editorconfig @@ -153,3 +153,15 @@ dotnet_diagnostic.IDE0032.severity = none # Excluded becuase of inconsistency with other analyzers [*.{cs,vb}] dotnet_diagnostic.IDE0036.severity = none + +# Order modifiers +# https://learn.microsoft.com/en-us/dotnet/fundamentals/code-analysis/style-rules/ide0036 +# Excluded becuase of inconsistency with other analyzers +[*.{cs,vb}] +dotnet_diagnostic.IDE0036.severity = none + +# Use 'System.Threading.Lock' +# https://learn.microsoft.com/en-us/dotnet/fundamentals/code-analysis/style-rules/ide0330 +# Excluded while TFMs are less than net9.0 +[*.{cs,vb}] +dotnet_diagnostic.IDE0330.severity = none