From 0a582f2c145a5318324d62ad58a11d9b37baf53b Mon Sep 17 00:00:00 2001 From: Mirko Da Corte Date: Thu, 21 Mar 2024 20:48:38 +0100 Subject: [PATCH] support dotnet 8 --- .github/workflows/myget-unstable-deploy.yml | 41 ++++++------- .github/workflows/nuget-stable-deploy.yml | 46 ++++++++------- MongODM.sln | 7 +++ MongODM.sln.DotSettings | 4 +- .../AspNetCoreSample/AspNetCoreSample.csproj | 2 +- .../Areas/MongODM/Pages/Index.cshtml.cs | 3 +- .../MongODM.AspNetCore.UI.csproj | 2 +- .../ServiceCollectionExtensions.cs | 3 +- src/MongODM.AspNetCore/DbDependencies.cs | 3 +- .../ApplicationBuilderExtensions.cs | 3 +- .../MongODM.AspNetCore.csproj | 2 +- .../MongODMConfiguration.cs | 3 +- ...calProxyTolerantDiscriminatorConvention.cs | 8 ++- src/MongODM.Core/DbContext.cs | 30 ++++++++-- .../ModelMaps/DbMigrationOperationMap.cs | 2 +- .../Domain/ModelMaps/ModelBaseMap.cs | 2 +- .../Domain/ModelMaps/OperationBaseMap.cs | 2 +- .../Domain/ModelMaps/SeedOperationMap.cs | 2 +- .../Domain/Models/DbMigrationOperation.cs | 6 +- .../Domain/Models/OperationBase.cs | 3 +- .../Extensions/BsonClassMapExtensions.cs | 15 +++-- .../Extensions/BsonMemberMapExtensions.cs | 3 +- .../Extensions/MemberInfoExtensions.cs | 29 ++++++---- .../UnmappedFieldDefinition.cs | 6 +- .../MemberMapEqFilterDefinition.cs | 4 +- .../Migration/DocumentMigration.cs | 2 +- src/MongODM.Core/MongODM.Core.csproj | 2 +- .../ProxyModels/AuditableInterceptor.cs | 8 +-- .../ProxyModels/ModelInterceptorBase.cs | 8 +-- .../ProxyModels/ProxyGenerator.cs | 25 ++++---- .../ProxyModels/ReferenceableInterceptor.cs | 13 ++--- src/MongODM.Core/ReflectionHelper.cs | 34 +++++------ .../Repositories/AsyncCursorWrapper.cs | 16 ++---- src/MongODM.Core/Repositories/Repository.cs | 45 ++++++--------- .../Repositories/RepositoryRegistry.cs | 11 ++-- .../Mapping/CustomSerializerMap.cs | 2 +- .../Mapping/DiscriminatorRegistry.cs | 57 ++++++++++++------- .../Mapping/ElementRepresentationBase.cs | 2 +- .../Serialization/Mapping/MapRegistry.cs | 42 +++++++------- .../Mapping/MemberMapRenderHelper.cs | 8 +++ .../Serialization/Mapping/ModelMap.cs | 15 +++-- .../Serialization/Mapping/ModelMapSchema.cs | 19 +++---- .../Modifiers/CacheSerializerModifier.cs | 5 +- .../Modifiers/ReferenceSerializerModifier.cs | 8 +-- .../ModelMapSerializationProvider.cs | 5 +- .../Serializers/DictionarySerializer.cs | 4 +- .../Serializers/EnumerableSerializer.cs | 6 +- .../Serializers/ExtraElementsSerializer.cs | 3 +- .../Serializers/HexToBinaryDataSerializer.cs | 6 +- .../Serializers/ModelMapSerializer.cs | 9 +-- .../ReadOnlyDictionarySerializer.cs | 4 +- .../Serializers/ReferenceSerializer.cs | 18 ++---- .../ReferenceSerializerConfiguration.cs | 22 +++---- .../Tasks/MigrateDbContextTask.cs | 2 +- .../Tasks/UpdateDocDependenciesTask.cs | 34 ++++++----- src/MongODM.Core/Utility/DbCache.cs | 9 +-- .../Utility/DbExecutionContextHandler.cs | 3 +- src/MongODM.Core/Utility/DbMaintainer.cs | 3 +- .../Utility/DbMigrationManager.cs | 3 +- src/MongODM.Core/Utility/FreezableConfig.cs | 6 +- .../AsyncLocalContextHangfireFilter.cs | 18 +++--- src/MongODM.Hangfire/MongODM.Hangfire.csproj | 2 +- .../Tasks/MigrateDbContextTaskFacade.cs | 6 +- .../Tasks/UpdateDocDependenciesTaskFacade.cs | 6 +- src/MongODM/MongODM.csproj | 2 +- .../MongODM.Core.Tests.csproj | 2 +- 66 files changed, 358 insertions(+), 368 deletions(-) diff --git a/.github/workflows/myget-unstable-deploy.yml b/.github/workflows/myget-unstable-deploy.yml index b42506c..55be51d 100644 --- a/.github/workflows/myget-unstable-deploy.yml +++ b/.github/workflows/myget-unstable-deploy.yml @@ -3,33 +3,36 @@ name: Unstable release deploy to MyGet on: push: branches: - - dev - - 'release/**' + - dev + - 'hotfix/**' + - 'release/**' jobs: build-test-package: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v3 - with: - fetch-depth: 0 + - name: Checkout + uses: actions/checkout@v4 + with: + fetch-depth: 0 - - name: Setup dotnet - uses: actions/setup-dotnet@v3 - with: - dotnet-version: | - 6.0.x - 7.0.x + - name: Setup dotnet + uses: actions/setup-dotnet@v4 + with: + dotnet-version: | + 6.0.x + 7.0.x + 8.0.x - - name: Build with dotnet - run: dotnet build --configuration Release + - name: Build with dotnet + run: dotnet build --configuration Release - - name: Run unit tests - run: dotnet test --configuration Release + - name: Run unit tests + run: dotnet test --configuration Release - - name: Generate nuget package - run: dotnet pack --configuration Release -o nupkg + - name: Generate nuget package + run: dotnet pack --configuration Release -o nupkg - - name: Push packages - run: dotnet nuget push './nupkg/*.nupkg' --api-key ${{secrets.MYGET_APIKEY}} --source https://www.myget.org/F/etherna/api/v3/index.json + - name: Push packages + run: dotnet nuget push './nupkg/*.nupkg' --api-key ${{secrets.MYGET_APIKEY}} --source https://www.myget.org/F/etherna/api/v3/index.json diff --git a/.github/workflows/nuget-stable-deploy.yml b/.github/workflows/nuget-stable-deploy.yml index 2d65ecb..8a99487 100644 --- a/.github/workflows/nuget-stable-deploy.yml +++ b/.github/workflows/nuget-stable-deploy.yml @@ -10,25 +10,27 @@ jobs: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v3 - with: - fetch-depth: 0 - - - name: Setup dotnet - uses: actions/setup-dotnet@v3 - with: - dotnet-version: | - 6.0.x - 7.0.x - - - name: Build with dotnet - run: dotnet build --configuration Release - - - name: Run unit tests - run: dotnet test --configuration Release - - - name: Generate nuget package - run: dotnet pack --configuration Release -o nupkg - - - name: Push packages - run: dotnet nuget push './nupkg/*.nupkg' --api-key ${{secrets.NUGET_KEY}} --source https://api.nuget.org/v3/index.json + - name: Checkout + uses: actions/checkout@v4 + with: + fetch-depth: 0 + + - name: Setup dotnet + uses: actions/setup-dotnet@v4 + with: + dotnet-version: | + 6.0.x + 7.0.x + 8.0.x + + - name: Build with dotnet + run: dotnet build --configuration Release + + - name: Run unit tests + run: dotnet test --configuration Release + + - name: Generate nuget package + run: dotnet pack --configuration Release -o nupkg + + - name: Push packages + run: dotnet nuget push './nupkg/*.nupkg' --api-key ${{secrets.NUGET_KEY}} --source https://api.nuget.org/v3/index.json diff --git a/MongODM.sln b/MongODM.sln index f7f7b05..135e839 100644 --- a/MongODM.sln +++ b/MongODM.sln @@ -31,6 +31,12 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "MongODM.AspNetCore.UI", "sr EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "AspNetCoreSample", "samples\AspNetCoreSample\AspNetCoreSample.csproj", "{E4DE982C-B684-40B0-A647-565363332BF3}" EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "workflows", "workflows", "{5F6B8B10-C8E6-458C-9CF7-52ACDECF662D}" + ProjectSection(SolutionItems) = preProject + .github\workflows\myget-unstable-deploy.yml = .github\workflows\myget-unstable-deploy.yml + .github\workflows\nuget-stable-deploy.yml = .github\workflows\nuget-stable-deploy.yml + EndProjectSection +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -77,6 +83,7 @@ Global {0C53354C-B5F3-438A-A5EA-26C6F7E92E38} = {490DAED7-DAD8-459A-A20E-F57F2F6F619E} {A1821261-1FEE-430E-84CC-8D88867D4011} = {490DAED7-DAD8-459A-A20E-F57F2F6F619E} {E4DE982C-B684-40B0-A647-565363332BF3} = {00FD3F85-6217-4947-9D26-7B2E9A8920CF} + {5F6B8B10-C8E6-458C-9CF7-52ACDECF662D} = {03C64D98-FF9F-4760-AE82-203953FF4940} EndGlobalSection GlobalSection(ExtensibilityGlobals) = postSolution SolutionGuid = {43A8089E-9445-4DE1-B509-F049E211B555} diff --git a/MongODM.sln.DotSettings b/MongODM.sln.DotSettings index 2cda9b2..f9b7284 100644 --- a/MongODM.sln.DotSettings +++ b/MongODM.sln.DotSettings @@ -11,4 +11,6 @@ Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and -limitations under the License. \ No newline at end of file +limitations under the License. + True + True \ No newline at end of file diff --git a/samples/AspNetCoreSample/AspNetCoreSample.csproj b/samples/AspNetCoreSample/AspNetCoreSample.csproj index 591d1e6..56d01ac 100644 --- a/samples/AspNetCoreSample/AspNetCoreSample.csproj +++ b/samples/AspNetCoreSample/AspNetCoreSample.csproj @@ -1,7 +1,7 @@ - net7.0 + net8.0 Etherna.MongODM.AspNetCoreSample Etherna SA diff --git a/src/MongODM.AspNetCore.UI/Areas/MongODM/Pages/Index.cshtml.cs b/src/MongODM.AspNetCore.UI/Areas/MongODM/Pages/Index.cshtml.cs index a08d215..cbec24c 100644 --- a/src/MongODM.AspNetCore.UI/Areas/MongODM/Pages/Index.cshtml.cs +++ b/src/MongODM.AspNetCore.UI/Areas/MongODM/Pages/Index.cshtml.cs @@ -35,8 +35,7 @@ public IndexModel( IOptions options, IServiceProvider serviceProvider) { - if (options is null) - throw new ArgumentNullException(nameof(options)); + ArgumentNullException.ThrowIfNull(options, nameof(options)); this.options = options.Value; this.serviceProvider = serviceProvider; diff --git a/src/MongODM.AspNetCore.UI/MongODM.AspNetCore.UI.csproj b/src/MongODM.AspNetCore.UI/MongODM.AspNetCore.UI.csproj index 3d862d4..b547a30 100644 --- a/src/MongODM.AspNetCore.UI/MongODM.AspNetCore.UI.csproj +++ b/src/MongODM.AspNetCore.UI/MongODM.AspNetCore.UI.csproj @@ -1,7 +1,7 @@  - net6.0;net7.0 + net6.0;net7.0;net8.0 true true Etherna.MongODM.AspNetCore.UI diff --git a/src/MongODM.AspNetCore.UI/ServiceCollectionExtensions.cs b/src/MongODM.AspNetCore.UI/ServiceCollectionExtensions.cs index dd7a4f7..d10fc68 100644 --- a/src/MongODM.AspNetCore.UI/ServiceCollectionExtensions.cs +++ b/src/MongODM.AspNetCore.UI/ServiceCollectionExtensions.cs @@ -31,8 +31,7 @@ public static IServiceCollection AddMongODMAdminDashboard( this IServiceCollection services, DashboardOptions? dashboardOptions = null) { - if (services is null) - throw new ArgumentNullException(nameof(services)); + ArgumentNullException.ThrowIfNull(services, nameof(services)); dashboardOptions ??= new DashboardOptions(); diff --git a/src/MongODM.AspNetCore/DbDependencies.cs b/src/MongODM.AspNetCore/DbDependencies.cs index 0e4a1fc..24f76b7 100644 --- a/src/MongODM.AspNetCore/DbDependencies.cs +++ b/src/MongODM.AspNetCore/DbDependencies.cs @@ -41,8 +41,7 @@ public DbDependencies( IRepositoryRegistry repositoryRegistry, ISerializerModifierAccessor serializerModifierAccessor) { - if (mongODMOptions is null) - throw new ArgumentNullException(nameof(mongODMOptions)); + ArgumentNullException.ThrowIfNull(mongODMOptions, nameof(mongODMOptions)); BsonSerializerRegistry = bsonSerializerRegistry; DbCache = dbCache; DbMaintainer = dbMaintainer; diff --git a/src/MongODM.AspNetCore/Extensions/ApplicationBuilderExtensions.cs b/src/MongODM.AspNetCore/Extensions/ApplicationBuilderExtensions.cs index 153fe3e..c1c2f81 100644 --- a/src/MongODM.AspNetCore/Extensions/ApplicationBuilderExtensions.cs +++ b/src/MongODM.AspNetCore/Extensions/ApplicationBuilderExtensions.cs @@ -30,8 +30,7 @@ public static class ApplicationBuilderExtensions public static IApplicationBuilder SeedDbContexts( this IApplicationBuilder builder) { - if (builder is null) - throw new ArgumentNullException(nameof(builder)); + ArgumentNullException.ThrowIfNull(builder, nameof(builder)); var serviceProvider = builder.ApplicationServices; var mongODMOptions = serviceProvider.GetRequiredService>(); diff --git a/src/MongODM.AspNetCore/MongODM.AspNetCore.csproj b/src/MongODM.AspNetCore/MongODM.AspNetCore.csproj index 2ac3046..7a943ab 100644 --- a/src/MongODM.AspNetCore/MongODM.AspNetCore.csproj +++ b/src/MongODM.AspNetCore/MongODM.AspNetCore.csproj @@ -1,7 +1,7 @@  - net6.0;net7.0 + net6.0;net7.0;net8.0 true Etherna.MongODM.AspNetCore Etherna SA diff --git a/src/MongODM.AspNetCore/MongODMConfiguration.cs b/src/MongODM.AspNetCore/MongODMConfiguration.cs index 5bc8859..f19f861 100644 --- a/src/MongODM.AspNetCore/MongODMConfiguration.cs +++ b/src/MongODM.AspNetCore/MongODMConfiguration.cs @@ -148,8 +148,7 @@ public IMongODMConfiguration AddDbContext( public void Freeze(IMongODMOptionsBuilder mongODMOptionsBuilder) { - if (mongODMOptionsBuilder is null) - throw new ArgumentNullException(nameof(mongODMOptionsBuilder)); + ArgumentNullException.ThrowIfNull(mongODMOptionsBuilder, nameof(mongODMOptionsBuilder)); configLock.EnterReadLock(); try diff --git a/src/MongODM.Core/Conventions/HierarchicalProxyTolerantDiscriminatorConvention.cs b/src/MongODM.Core/Conventions/HierarchicalProxyTolerantDiscriminatorConvention.cs index 92ce207..bd5bd79 100644 --- a/src/MongODM.Core/Conventions/HierarchicalProxyTolerantDiscriminatorConvention.cs +++ b/src/MongODM.Core/Conventions/HierarchicalProxyTolerantDiscriminatorConvention.cs @@ -21,6 +21,7 @@ using Etherna.MongODM.Core.Utility; using System; using System.Collections.Generic; +using System.Diagnostics.CodeAnalysis; using System.Linq; namespace Etherna.MongODM.Core.Conventions @@ -32,6 +33,8 @@ public class HierarchicalProxyTolerantDiscriminatorConvention : IDiscriminatorCo private readonly IExecutionContext? executionContext; // Constructors. + [SuppressMessage("Usage", "CA2249:Consider using \'string.Contains\' instead of \'string.IndexOf\'")] + [SuppressMessage("Globalization", "CA1307:Specify StringComparison for clarity")] public HierarchicalProxyTolerantDiscriminatorConvention( IDbContext dbContext, string elementName) @@ -49,6 +52,8 @@ public HierarchicalProxyTolerantDiscriminatorConvention( /// /// Discriminator element name /// Execution context + [SuppressMessage("Usage", "CA2249:Consider using \'string.Contains\' instead of \'string.IndexOf\'")] + [SuppressMessage("Globalization", "CA1307:Specify StringComparison for clarity")] public HierarchicalProxyTolerantDiscriminatorConvention( string elementName, IExecutionContext executionContext) @@ -81,8 +86,7 @@ public IDbContext DbContext // Methods. public Type GetActualType(IBsonReader bsonReader, Type nominalType) { - if (bsonReader is null) - throw new ArgumentNullException(nameof(bsonReader)); + ArgumentNullException.ThrowIfNull(bsonReader, nameof(bsonReader)); //the BsonReader is sitting at the value whose actual type needs to be found var bsonType = bsonReader.GetCurrentBsonType(); diff --git a/src/MongODM.Core/DbContext.cs b/src/MongODM.Core/DbContext.cs index 4f4e450..8fa3be9 100644 --- a/src/MongODM.Core/DbContext.cs +++ b/src/MongODM.Core/DbContext.cs @@ -39,12 +39,13 @@ namespace Etherna.MongODM.Core { - public abstract class DbContext : IDbContext, IDbContextBuilder + public abstract class DbContext : IDbContext, IDbContextBuilder, IDisposable { // Fields. private bool? _isSeeded; private BsonSerializerRegistry _serializerRegistry = default!; private IEnumerable childDbContexts = default!; + private bool disposed; private bool isInitialized; private readonly ReaderWriterLockSlim isSeededLock = new(); //support read/write locks private readonly ILogger logger; @@ -64,10 +65,8 @@ public void Initialize( { if (isInitialized) throw new InvalidOperationException("DbContext already initialized"); - if (dependencies is null) - throw new ArgumentNullException(nameof(dependencies)); - if (options is null) - throw new ArgumentNullException(nameof(options)); + ArgumentNullException.ThrowIfNull(dependencies, nameof(dependencies)); + ArgumentNullException.ThrowIfNull(options, nameof(options)); // Set dependencies. this.childDbContexts = childDbContexts; @@ -126,6 +125,27 @@ public void Initialize( logger.DbContextInitialized(options.DbName); } + + // Dispose. + public void Dispose() + { + Dispose(true); + GC.SuppressFinalize(this); + } + + protected virtual void Dispose(bool disposing) + { + if (disposed) return; + + // Dispose managed resources. + if (disposing) + { + isSeededLock.Dispose(); + seedingSemaphore.Dispose(); + } + + disposed = true; + } // Public properties. public IReadOnlyCollection ChangedModelsList => diff --git a/src/MongODM.Core/Domain/ModelMaps/DbMigrationOperationMap.cs b/src/MongODM.Core/Domain/ModelMaps/DbMigrationOperationMap.cs index 334d485..a6eba54 100644 --- a/src/MongODM.Core/Domain/ModelMaps/DbMigrationOperationMap.cs +++ b/src/MongODM.Core/Domain/ModelMaps/DbMigrationOperationMap.cs @@ -18,7 +18,7 @@ namespace Etherna.MongODM.Core.Domain.ModelMaps { - class DbMigrationOperationMap : IModelMapsCollector + internal sealed class DbMigrationOperationMap : IModelMapsCollector { public void Register(IDbContext dbContext) { diff --git a/src/MongODM.Core/Domain/ModelMaps/ModelBaseMap.cs b/src/MongODM.Core/Domain/ModelMaps/ModelBaseMap.cs index c033d46..1a46f5b 100644 --- a/src/MongODM.Core/Domain/ModelMaps/ModelBaseMap.cs +++ b/src/MongODM.Core/Domain/ModelMaps/ModelBaseMap.cs @@ -20,7 +20,7 @@ namespace Etherna.MongODM.Core.Domain.ModelMaps { - class ModelBaseMap : IModelMapsCollector + internal sealed class ModelBaseMap : IModelMapsCollector { public void Register(IDbContext dbContext) { diff --git a/src/MongODM.Core/Domain/ModelMaps/OperationBaseMap.cs b/src/MongODM.Core/Domain/ModelMaps/OperationBaseMap.cs index eca9342..c728469 100644 --- a/src/MongODM.Core/Domain/ModelMaps/OperationBaseMap.cs +++ b/src/MongODM.Core/Domain/ModelMaps/OperationBaseMap.cs @@ -18,7 +18,7 @@ namespace Etherna.MongODM.Core.Domain.ModelMaps { - class OperationBaseMap : IModelMapsCollector + internal sealed class OperationBaseMap : IModelMapsCollector { public void Register(IDbContext dbContext) { diff --git a/src/MongODM.Core/Domain/ModelMaps/SeedOperationMap.cs b/src/MongODM.Core/Domain/ModelMaps/SeedOperationMap.cs index 2cb14a0..cdaeb20 100644 --- a/src/MongODM.Core/Domain/ModelMaps/SeedOperationMap.cs +++ b/src/MongODM.Core/Domain/ModelMaps/SeedOperationMap.cs @@ -17,7 +17,7 @@ namespace Etherna.MongODM.Core.Domain.ModelMaps { - class SeedOperationMap : IModelMapsCollector + internal sealed class SeedOperationMap : IModelMapsCollector { public void Register(IDbContext dbContext) { diff --git a/src/MongODM.Core/Domain/Models/DbMigrationOperation.cs b/src/MongODM.Core/Domain/Models/DbMigrationOperation.cs index 309a2e6..335d1b5 100644 --- a/src/MongODM.Core/Domain/Models/DbMigrationOperation.cs +++ b/src/MongODM.Core/Domain/Models/DbMigrationOperation.cs @@ -56,8 +56,7 @@ public virtual IEnumerable Logs [PropertyAlterer(nameof(Logs))] public virtual void AddLog(MigrationLogBase log) { - if (log is null) - throw new ArgumentNullException(nameof(log)); + ArgumentNullException.ThrowIfNull(log, nameof(log)); _logs.Add(log); } @@ -97,8 +96,7 @@ public virtual void TaskFailed() [PropertyAlterer(nameof(TaskId))] public virtual void TaskStarted(string taskId) { - if (taskId is null) - throw new ArgumentNullException(nameof(taskId)); + ArgumentNullException.ThrowIfNull(taskId, nameof(taskId)); if (CurrentStatus != Status.New) throw new InvalidOperationException(); diff --git a/src/MongODM.Core/Domain/Models/OperationBase.cs b/src/MongODM.Core/Domain/Models/OperationBase.cs index 9c0161d..07d5fb0 100644 --- a/src/MongODM.Core/Domain/Models/OperationBase.cs +++ b/src/MongODM.Core/Domain/Models/OperationBase.cs @@ -21,8 +21,7 @@ public abstract class OperationBase : EntityModelBase // Constructors and dispose. protected OperationBase(IDbContext dbContext) { - if (dbContext is null) - throw new ArgumentNullException(nameof(dbContext)); + ArgumentNullException.ThrowIfNull(dbContext, nameof(dbContext)); CreationDateTime = DateTime.Now; DbContextName = dbContext.Identifier; diff --git a/src/MongODM.Core/Extensions/BsonClassMapExtensions.cs b/src/MongODM.Core/Extensions/BsonClassMapExtensions.cs index 4dadff2..e72d0f2 100644 --- a/src/MongODM.Core/Extensions/BsonClassMapExtensions.cs +++ b/src/MongODM.Core/Extensions/BsonClassMapExtensions.cs @@ -25,15 +25,14 @@ public static class BsonClassMapExtensions { public static bool IsEntity(this BsonClassMap classMap) { - if (classMap is null) - throw new ArgumentNullException(nameof(classMap)); + ArgumentNullException.ThrowIfNull(classMap, nameof(classMap)); return classMap.IdMemberMap != null; } public static void SetBaseClassMap(this BsonClassMap classMap, BsonClassMap baseClassMap) { - typeof(BsonClassMap).GetField("_baseClassMap", BindingFlags.Instance | BindingFlags.NonPublic) + typeof(BsonClassMap).GetField("_baseClassMap", BindingFlags.Instance | BindingFlags.NonPublic)! .SetValue(classMap, baseClassMap); } @@ -42,8 +41,7 @@ public static BsonMemberMap SetMemberSerializer( Expression> memberLambda, IBsonSerializer serializer) { - if (classMap is null) - throw new ArgumentNullException(nameof(classMap)); + ArgumentNullException.ThrowIfNull(classMap, nameof(classMap)); var member = classMap.GetMemberMap(memberLambda); member ??= classMap.MapMember(memberLambda); @@ -57,8 +55,7 @@ public static BsonMemberMap SetMemberSerializer { - if (serializer is null) - throw new ArgumentNullException(nameof(serializer)); + ArgumentNullException.ThrowIfNull(serializer, nameof(serializer)); if (typeof(TMember) == typeof(TSerializer)) return classMap.SetMemberSerializer(memberLambda, (IBsonSerializer)serializer); @@ -69,9 +66,11 @@ public static BsonMemberMap SetMemberSerializer); var classMapSerializerType = classMapSerializerDefinition.MakeGenericType(classMap.ClassType); - return (IBsonSerializer)Activator.CreateInstance(classMapSerializerType, classMap); + return (IBsonSerializer)Activator.CreateInstance(classMapSerializerType, classMap)!; } } } diff --git a/src/MongODM.Core/Extensions/BsonMemberMapExtensions.cs b/src/MongODM.Core/Extensions/BsonMemberMapExtensions.cs index c762f16..bae2062 100644 --- a/src/MongODM.Core/Extensions/BsonMemberMapExtensions.cs +++ b/src/MongODM.Core/Extensions/BsonMemberMapExtensions.cs @@ -21,8 +21,7 @@ public static class BsonMemberMapExtensions { public static bool IsIdMember(this BsonMemberMap memberMap) { - if (memberMap is null) - throw new ArgumentNullException(nameof(memberMap)); + ArgumentNullException.ThrowIfNull(memberMap, nameof(memberMap)); return memberMap.ClassMap.IdMemberMap == memberMap; } diff --git a/src/MongODM.Core/Extensions/MemberInfoExtensions.cs b/src/MongODM.Core/Extensions/MemberInfoExtensions.cs index f5b175d..c4e5e88 100644 --- a/src/MongODM.Core/Extensions/MemberInfoExtensions.cs +++ b/src/MongODM.Core/Extensions/MemberInfoExtensions.cs @@ -20,16 +20,23 @@ namespace Etherna.MongODM.Core.Extensions public static class MemberInfoExtensions { public static bool IsSameAs(this MemberInfo memberInfo, MemberInfo otherMemberInfo) - => memberInfo == null - ? otherMemberInfo == null - : (otherMemberInfo != null && - (Equals(memberInfo, otherMemberInfo) - || (memberInfo.Name == otherMemberInfo.Name - && (memberInfo.DeclaringType == otherMemberInfo.DeclaringType - || memberInfo.DeclaringType.GetTypeInfo().IsSubclassOf(otherMemberInfo.DeclaringType) - || otherMemberInfo.DeclaringType.GetTypeInfo().IsSubclassOf(memberInfo.DeclaringType) - || memberInfo.DeclaringType.GetTypeInfo().ImplementedInterfaces.Contains(otherMemberInfo.DeclaringType) - || otherMemberInfo.DeclaringType.GetTypeInfo().ImplementedInterfaces - .Contains(memberInfo.DeclaringType))))); + { + if (memberInfo == null) + return otherMemberInfo == null; + if (otherMemberInfo == null) + return false; + if (Equals(memberInfo, otherMemberInfo)) + return true; + if (memberInfo.Name != otherMemberInfo.Name) + return false; + + var memberInfoDeclaringType = memberInfo.DeclaringType!; + var otherMemberInfoDeclaringType = otherMemberInfo.DeclaringType!; + return memberInfoDeclaringType == otherMemberInfoDeclaringType || + memberInfoDeclaringType.GetTypeInfo().IsSubclassOf(otherMemberInfoDeclaringType) || + otherMemberInfoDeclaringType.GetTypeInfo().IsSubclassOf(memberInfoDeclaringType) || + memberInfoDeclaringType.GetTypeInfo().ImplementedInterfaces.Contains(otherMemberInfo.DeclaringType) || + otherMemberInfoDeclaringType.GetTypeInfo().ImplementedInterfaces.Contains(memberInfo.DeclaringType); + } } } diff --git a/src/MongODM.Core/FieldDefinition/UnmappedFieldDefinition.cs b/src/MongODM.Core/FieldDefinition/UnmappedFieldDefinition.cs index ea80e21..c935409 100644 --- a/src/MongODM.Core/FieldDefinition/UnmappedFieldDefinition.cs +++ b/src/MongODM.Core/FieldDefinition/UnmappedFieldDefinition.cs @@ -28,7 +28,8 @@ public UnmappedFieldDefinition( string unmappedFieldName, IBsonSerializer unmappedFieldSerializer) { - if (unmappedFieldName.Contains(".")) + ArgumentNullException.ThrowIfNull(unmappedFieldName, nameof(unmappedFieldName)); + if (unmappedFieldName.Contains('.', StringComparison.InvariantCulture)) throw new ArgumentException("Field name can't navigate nested documents", nameof(unmappedFieldName)); BaseDocumentField = baseDocumentField; @@ -58,7 +59,8 @@ public UnmappedFieldDefinition( string unmappedFieldName, IBsonSerializer unmappedFieldSerializer) { - if (unmappedFieldName.Contains(".")) + ArgumentNullException.ThrowIfNull(unmappedFieldName, nameof(unmappedFieldName)); + if (unmappedFieldName.Contains('.', StringComparison.InvariantCulture)) throw new ArgumentException("Field name can't navigate nested documents", nameof(unmappedFieldName)); BaseDocumentField = baseDocumentField; diff --git a/src/MongODM.Core/FilterDefinition/MemberMapEqFilterDefinition.cs b/src/MongODM.Core/FilterDefinition/MemberMapEqFilterDefinition.cs index a879740..35eccf9 100644 --- a/src/MongODM.Core/FilterDefinition/MemberMapEqFilterDefinition.cs +++ b/src/MongODM.Core/FilterDefinition/MemberMapEqFilterDefinition.cs @@ -40,6 +40,8 @@ public MemberMapEqFilterDefinition( IMemberMap memberMap, TItem value) { + ArgumentNullException.ThrowIfNull(memberMap, nameof(memberMap)); + if (memberMap.ElementPathHasUndefinedDocumentElement) throw new ArgumentException("Can't create filter with member map path having undefined document elements"); @@ -61,7 +63,7 @@ public override BsonDocument Render(IBsonSerializer documentSerialize } // Helpers. - private BsonDocument BuildBsonDocument(IEnumerable segmentedField, TItem value, IBsonSerializer valueSerializer) + private static BsonDocument BuildBsonDocument(IEnumerable segmentedField, TItem value, IBsonSerializer valueSerializer) { // Recursion building elemMatch filters. var sb = new StringBuilder(); diff --git a/src/MongODM.Core/Migration/DocumentMigration.cs b/src/MongODM.Core/Migration/DocumentMigration.cs index 7c88549..f70b027 100644 --- a/src/MongODM.Core/Migration/DocumentMigration.cs +++ b/src/MongODM.Core/Migration/DocumentMigration.cs @@ -111,7 +111,7 @@ public override Task MigrateAsync( await sourceCollection.Find(FilterDefinition.Empty, new FindOptions { NoCursorTimeout = true }) .ForEachAsync(async model => { - await sourceModelProcessorActionAsync(model); + await sourceModelProcessorActionAsync(model).ConfigureAwait(false); // Increment counter. totMigratedDocuments++; diff --git a/src/MongODM.Core/MongODM.Core.csproj b/src/MongODM.Core/MongODM.Core.csproj index 9997619..536afe3 100644 --- a/src/MongODM.Core/MongODM.Core.csproj +++ b/src/MongODM.Core/MongODM.Core.csproj @@ -1,7 +1,7 @@  - netstandard2.0 + net6.0;net7.0;net8.0 true Etherna.MongODM.Core Etherna SA diff --git a/src/MongODM.Core/ProxyModels/AuditableInterceptor.cs b/src/MongODM.Core/ProxyModels/AuditableInterceptor.cs index f37d528..1c567dc 100644 --- a/src/MongODM.Core/ProxyModels/AuditableInterceptor.cs +++ b/src/MongODM.Core/ProxyModels/AuditableInterceptor.cs @@ -35,8 +35,7 @@ public AuditableInterceptor(IEnumerable additionalInterfaces) // Protected methods. protected override bool InterceptInterface(IInvocation invocation) { - if (invocation is null) - throw new ArgumentNullException(nameof(invocation)); + ArgumentNullException.ThrowIfNull(invocation, nameof(invocation)); // Intercept ISummarizable invocations if (invocation.Method.DeclaringType == typeof(IAuditable)) @@ -44,7 +43,7 @@ protected override bool InterceptInterface(IInvocation invocation) if (invocation.Method.Name == $"get_{nameof(IAuditable.IsAuditingEnabled)}") invocation.ReturnValue = isAuditingEnabled; else if (invocation.Method.Name == $"get_{nameof(IAuditable.IsChanged)}") - invocation.ReturnValue = changedMembers.Any(); + invocation.ReturnValue = changedMembers.Count != 0; else if (invocation.Method.Name == $"get_{nameof(IAuditable.ChangedMembers)}") invocation.ReturnValue = changedMembers; else if (invocation.Method.Name == nameof(IAuditable.DisableAuditing)) @@ -64,8 +63,7 @@ protected override bool InterceptInterface(IInvocation invocation) protected override void InterceptModel(IInvocation invocation) { - if (invocation is null) - throw new ArgumentNullException(nameof(invocation)); + ArgumentNullException.ThrowIfNull(invocation, nameof(invocation)); // Filter sets. if (isAuditingEnabled) diff --git a/src/MongODM.Core/ProxyModels/ModelInterceptorBase.cs b/src/MongODM.Core/ProxyModels/ModelInterceptorBase.cs index e9e0757..c4f6470 100644 --- a/src/MongODM.Core/ProxyModels/ModelInterceptorBase.cs +++ b/src/MongODM.Core/ProxyModels/ModelInterceptorBase.cs @@ -30,8 +30,7 @@ protected ModelInterceptorBase(IEnumerable additionalInterfaces) public void Intercept(IInvocation invocation) { - if (invocation is null) - throw new ArgumentNullException(nameof(invocation)); + ArgumentNullException.ThrowIfNull(invocation, nameof(invocation)); if (additionalInterfaces.Contains(invocation.Method.DeclaringType)) { @@ -44,7 +43,7 @@ public void Intercept(IInvocation invocation) { // Check model type. if (invocation.Method.DeclaringType != typeof(TModel) && - !invocation.Method.DeclaringType.IsAssignableFrom(typeof(TModel))) + !invocation.Method.DeclaringType!.IsAssignableFrom(typeof(TModel))) { throw new InvalidOperationException(); } @@ -69,8 +68,7 @@ protected virtual bool InterceptInterface(IInvocation invocation) /// Current invocation protected virtual void InterceptModel(IInvocation invocation) { - if (invocation is null) - throw new ArgumentNullException(nameof(invocation)); + ArgumentNullException.ThrowIfNull(invocation, nameof(invocation)); invocation.Proceed(); } diff --git a/src/MongODM.Core/ProxyModels/ProxyGenerator.cs b/src/MongODM.Core/ProxyModels/ProxyGenerator.cs index 5bc98ed..1b76197 100644 --- a/src/MongODM.Core/ProxyModels/ProxyGenerator.cs +++ b/src/MongODM.Core/ProxyModels/ProxyGenerator.cs @@ -75,10 +75,8 @@ public object CreateInstance( IDbContext dbContext, params object[] constructorArguments) { - if (dbContext is null) - throw new ArgumentNullException(nameof(dbContext)); - if (type is null) - throw new ArgumentNullException(nameof(type)); + ArgumentNullException.ThrowIfNull(dbContext, nameof(dbContext)); + ArgumentNullException.ThrowIfNull(type, nameof(type)); // If creation of proxy models are disabled, create a simple model instance. if (DisableCreationWithProxyTypes) @@ -88,7 +86,7 @@ public object CreateInstance( BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance, null, constructorArguments, - null); + null)!; } // Get configuration. @@ -97,9 +95,9 @@ public object CreateInstance( bool configurationFound = false; try { - if (modelConfigurationDictionary.ContainsKey(type)) + if (modelConfigurationDictionary.TryGetValue(type, out var conf)) { - configuration = modelConfigurationDictionary[type]; + configuration = conf; configurationFound = true; } } @@ -113,9 +111,9 @@ public object CreateInstance( modelConfigurationDictionaryLock.EnterWriteLock(); try { - if (modelConfigurationDictionary.ContainsKey(type)) + if (modelConfigurationDictionary.TryGetValue(type, out var conf)) { - configuration = modelConfigurationDictionary[type]; + configuration = conf; } else { @@ -187,11 +185,10 @@ public bool IsProxyType(Type type) public Type PurgeProxyType(Type type) { - if (type is null) - throw new ArgumentNullException(nameof(type)); + ArgumentNullException.ThrowIfNull(type, nameof(type)); return IsProxyType(type) ? - type.BaseType : + type.BaseType! : type; } @@ -241,7 +238,7 @@ private Func GetInterceptorInstancer( interceptorInstancers.Add(dbContext => (IInterceptor)Activator.CreateInstance( auditableInterceptorType, - additionalInterfaces)); + additionalInterfaces)!); //referenceableInterceptor var referenceableInterceptorType = typeof(ReferenceableInterceptor<,>).MakeGenericType(modelType, entityModelKeyType); @@ -253,7 +250,7 @@ private Func GetInterceptorInstancer( referenceableInterceptorType, additionalInterfaces, dbContext, - referenceableInterceptorLogger)); + referenceableInterceptorLogger)!); } return dbContext => (from instancer in interceptorInstancers diff --git a/src/MongODM.Core/ProxyModels/ReferenceableInterceptor.cs b/src/MongODM.Core/ProxyModels/ReferenceableInterceptor.cs index bd951ac..514ec1b 100644 --- a/src/MongODM.Core/ProxyModels/ReferenceableInterceptor.cs +++ b/src/MongODM.Core/ProxyModels/ReferenceableInterceptor.cs @@ -43,8 +43,7 @@ public ReferenceableInterceptor( ILogger> logger) : base(additionalInterfaces) { - if (dbContext is null) - throw new ArgumentNullException(nameof(dbContext)); + ArgumentNullException.ThrowIfNull(dbContext, nameof(dbContext)); repository = dbContext.RepositoryRegistry.GetRepositoryByHandledModelType(typeof(TModel)); this.logger = logger; @@ -53,8 +52,7 @@ public ReferenceableInterceptor( // Protected methods. protected override bool InterceptInterface(IInvocation invocation) { - if (invocation is null) - throw new ArgumentNullException(nameof(invocation)); + ArgumentNullException.ThrowIfNull(invocation, nameof(invocation)); // Intercept ISummarizable invocations if (invocation.Method.DeclaringType == typeof(IReferenceable)) @@ -79,7 +77,7 @@ protected override bool InterceptInterface(IInvocation invocation) { isSummary = true; - var summaryLoadedMemberNames = (invocation.GetArgumentValue(0) as IEnumerable).ToArray(); + var summaryLoadedMemberNames = ((IEnumerable)invocation.GetArgumentValue(0)).ToArray(); foreach (var memberName in summaryLoadedMemberNames) settedMemberNames[memberName] = true; } @@ -95,8 +93,7 @@ protected override bool InterceptInterface(IInvocation invocation) protected override void InterceptModel(IInvocation invocation) { - if (invocation is null) - throw new ArgumentNullException(nameof(invocation)); + ArgumentNullException.ThrowIfNull(invocation, nameof(invocation)); // Filter gets. if (invocation.Method.Name.StartsWith("get_", StringComparison.InvariantCulture) && isSummary) @@ -161,7 +158,7 @@ private async Task FullLoadAsync(TModel model) var fullModel = (await repository.TryFindOneAsync(model.Id).ConfigureAwait(false)) as TModel; MergeFullModel(model, fullModel); - logger.SummaryModelFullLoaded(typeof(TModel), model.Id.ToString()); + logger.SummaryModelFullLoaded(typeof(TModel), model.Id.ToString()!); } } diff --git a/src/MongODM.Core/ReflectionHelper.cs b/src/MongODM.Core/ReflectionHelper.cs index d26eb78..8bb35c6 100644 --- a/src/MongODM.Core/ReflectionHelper.cs +++ b/src/MongODM.Core/ReflectionHelper.cs @@ -28,8 +28,7 @@ public static class ReflectionHelper public static MemberInfo FindProperty(LambdaExpression lambdaExpression) { - if (lambdaExpression is null) - throw new ArgumentNullException(nameof(lambdaExpression)); + ArgumentNullException.ThrowIfNull(lambdaExpression, nameof(lambdaExpression)); Expression expressionToCheck = lambdaExpression; @@ -48,7 +47,7 @@ public static MemberInfo FindProperty(LambdaExpression lambdaExpression) case ExpressionType.MemberAccess: var memberExpression = (MemberExpression)expressionToCheck; - if (memberExpression.Expression.NodeType != ExpressionType.Parameter && + if (memberExpression.Expression!.NodeType != ExpressionType.Parameter && memberExpression.Expression.NodeType != ExpressionType.Convert) { throw new ArgumentException( @@ -70,12 +69,10 @@ public static MemberInfo FindProperty(LambdaExpression lambdaExpression) public static PropertyInfo FindPropertyImplementation(PropertyInfo interfacePropertyInfo, Type actualType) { - if (interfacePropertyInfo is null) - throw new ArgumentNullException(nameof(interfacePropertyInfo)); - if (actualType is null) - throw new ArgumentNullException(nameof(actualType)); + ArgumentNullException.ThrowIfNull(interfacePropertyInfo, nameof(interfacePropertyInfo)); + ArgumentNullException.ThrowIfNull(actualType, nameof(actualType)); - var interfaceType = interfacePropertyInfo.DeclaringType; + var interfaceType = interfacePropertyInfo.DeclaringType!; // An interface map must be used because because there is no // other officially documented way to derive the explicitly @@ -106,8 +103,7 @@ public static MemberInfo GetMemberInfoFromLambda( Expression> memberLambda, Type? actualType = null) { - if (memberLambda is null) - throw new ArgumentNullException(nameof(memberLambda)); + ArgumentNullException.ThrowIfNull(memberLambda, nameof(memberLambda)); var body = memberLambda.Body; MemberExpression memberExpression; @@ -130,7 +126,7 @@ public static MemberInfo GetMemberInfoFromLambda( break; case MemberTypes.Property: if (actualType?.IsInterface == false && - memberInfo.DeclaringType.IsInterface) + memberInfo.DeclaringType!.IsInterface) { memberInfo = FindPropertyImplementation((PropertyInfo)memberInfo, actualType); } @@ -172,13 +168,12 @@ public static TMember GetValueFromLambda(TModel source, Express /// The list of properties public static IEnumerable GetWritableInstanceProperties(Type objectType) { - if (objectType is null) - throw new ArgumentNullException(nameof(objectType)); + ArgumentNullException.ThrowIfNull(objectType, nameof(objectType)); propertyRegistryLock.EnterReadLock(); try { - if (propertyRegistry.TryGetValue(objectType, out IEnumerable value)) + if (propertyRegistry.TryGetValue(objectType, out IEnumerable? value)) return value; } finally @@ -189,7 +184,7 @@ public static IEnumerable GetWritableInstanceProperties(Type objec propertyRegistryLock.EnterWriteLock(); try { - if (!propertyRegistry.ContainsKey(objectType)) + if (!propertyRegistry.TryGetValue(objectType, out IEnumerable? value)) { var typeStack = new List(); var stackType = objectType; @@ -198,12 +193,13 @@ public static IEnumerable GetWritableInstanceProperties(Type objec typeStack.Add(stackType); stackType = stackType.BaseType; } while (stackType != null); - - propertyRegistry.Add(objectType, typeStack + + value = typeStack .SelectMany(type => type.GetProperties(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance)) - .Where(prop => prop.CanWrite)); + .Where(prop => prop.CanWrite); + propertyRegistry.Add(objectType, value); } - return propertyRegistry[objectType]; + return value; } finally { diff --git a/src/MongODM.Core/Repositories/AsyncCursorWrapper.cs b/src/MongODM.Core/Repositories/AsyncCursorWrapper.cs index 70fa565..1b040b2 100644 --- a/src/MongODM.Core/Repositories/AsyncCursorWrapper.cs +++ b/src/MongODM.Core/Repositories/AsyncCursorWrapper.cs @@ -21,7 +21,7 @@ namespace Etherna.MongODM.Core.Repositories { - internal class AsyncCursorWrapper : IAsyncCursor + internal sealed class AsyncCursorWrapper : IAsyncCursor { // Fields. private readonly IAsyncCursor cursor; @@ -38,23 +38,15 @@ public AsyncCursorWrapper( } public void Dispose() - { - Dispose(true); - GC.SuppressFinalize(this); - } - - protected virtual void Dispose(bool disposing) { if (disposed) return; // Dispose managed resources. - if (disposing) - { - cursor.Dispose(); - dbExecutionContextHandler.Dispose(); - } + cursor.Dispose(); + dbExecutionContextHandler.Dispose(); disposed = true; + GC.SuppressFinalize(this); } // Properties. diff --git a/src/MongODM.Core/Repositories/Repository.cs b/src/MongODM.Core/Repositories/Repository.cs index 28da138..140fabc 100644 --- a/src/MongODM.Core/Repositories/Repository.cs +++ b/src/MongODM.Core/Repositories/Repository.cs @@ -84,8 +84,7 @@ public async Task AccessToCollectionAsync( Func, Task> func, bool handleImplicitDbExecutionContext = true) { - if (func is null) - throw new ArgumentNullException(nameof(func)); + ArgumentNullException.ThrowIfNull(func, nameof(func)); // Initialize collection cache. _collection ??= DbContext.Database.GetCollection(options.Name); @@ -166,7 +165,7 @@ public virtual Task BuildIndexesAsync(CancellationToken cancellationToken = defa } // Build new indexes. - if (newIndexes.Any()) + if (newIndexes.Count != 0) await collection.Indexes.CreateManyAsync(newIndexes.Select(i => i.createIndex), cancellationToken).ConfigureAwait(false); logger.RepositoryBuiltIndexes(Name, DbContext.Options.DbName); @@ -182,19 +181,18 @@ public virtual async Task CreateAsync(IEnumerable models, CancellationTo { await CreateOnDBAsync(models, cancellationToken).ConfigureAwait(false); - logger.RepositoryCreatedDocuments(Name, DbContext.Options.DbName, models.Select(m => m.Id!.ToString())); + logger.RepositoryCreatedDocuments(Name, DbContext.Options.DbName, models.Select(m => m.Id!.ToString()!)); await DbContext.SaveChangesAsync(cancellationToken).ConfigureAwait(false); } public virtual async Task CreateAsync(TModel model, CancellationToken cancellationToken = default) { - if (model is null) - throw new ArgumentNullException(nameof(model)); + ArgumentNullException.ThrowIfNull(model, nameof(model)); await CreateOnDBAsync(model, cancellationToken).ConfigureAwait(false); - logger.RepositoryCreatedDocument(Name, DbContext.Options.DbName, model.Id!.ToString()); + logger.RepositoryCreatedDocument(Name, DbContext.Options.DbName, model.Id!.ToString()!); await DbContext.SaveChangesAsync(cancellationToken).ConfigureAwait(false); } @@ -207,8 +205,7 @@ public async Task DeleteAsync(TKey id, CancellationToken cancellationToken = def public virtual async Task DeleteAsync(TModel model, CancellationToken cancellationToken = default) { - if (model is null) - throw new ArgumentNullException(nameof(model)); + ArgumentNullException.ThrowIfNull(model, nameof(model)); // Unlink dependent models. model.DisposeForDelete(); @@ -221,7 +218,7 @@ public virtual async Task DeleteAsync(TModel model, CancellationToken cancellati if (DbContext.DbCache.LoadedModels.ContainsKey(model.Id!)) DbContext.DbCache.RemoveModel(model.Id!); - logger.RepositoryDeletedDocument(Name, DbContext.Options.DbName, model.Id!.ToString()); + logger.RepositoryDeletedDocument(Name, DbContext.Options.DbName, model.Id!.ToString()!); } public async Task DeleteAsync(IEntityModel model, CancellationToken cancellationToken = default) @@ -241,13 +238,13 @@ public virtual async Task> FindAsync( return await AccessToCollectionAsync(async collection => { - var resultCursor = await collection.FindAsync(filter, options, cancellationToken); + var resultCursor = await collection.FindAsync(filter, options, cancellationToken).ConfigureAwait(false); var wrappedCursor = new AsyncCursorWrapper(resultCursor, dbExecContextHandler); logger.RepositoryQueriedCollection(Name, DbContext.Options.DbName); return wrappedCursor; - }, false); + }, false).ConfigureAwait(false); } public async Task FindOneAsync(object id, CancellationToken cancellationToken = default) => @@ -274,14 +271,13 @@ public Task FindOneAsync( public string ModelIdToString(object model) { - if (model is null) - throw new ArgumentNullException(nameof(model)); + ArgumentNullException.ThrowIfNull(model, nameof(model)); if (model is not TModel typedModel) throw new ArgumentException($"Model is not of {model.GetType().Name} type", nameof(model)); if (typedModel.Id is null) throw new InvalidOperationException("Model Id can't be null"); - return typedModel.Id.ToString(); + return typedModel.Id.ToString()!; } public virtual Task QueryElementsAsync( @@ -289,8 +285,7 @@ public virtual Task QueryElementsAsync( AggregateOptions? aggregateOptions = null) => AccessToCollectionAsync(collection => { - if (query is null) - throw new ArgumentNullException(nameof(query)); + ArgumentNullException.ThrowIfNull(query, nameof(query)); var result = query(collection.AsQueryable(aggregateOptions)); @@ -380,8 +375,7 @@ public virtual Task ReplaceAsync( public async Task TryFindOneAsync(Expression> predicate, CancellationToken cancellationToken = default) { - if (predicate is null) - throw new ArgumentNullException(nameof(predicate)); + ArgumentNullException.ThrowIfNull(predicate, nameof(predicate)); try { @@ -403,8 +397,7 @@ protected virtual Task CreateOnDBAsync(TModel model, CancellationToken cancellat protected virtual Task DeleteOnDBAsync(TModel model, CancellationToken cancellationToken) => AccessToCollectionAsync(collection => { - if (model is null) - throw new ArgumentNullException(nameof(model)); + ArgumentNullException.ThrowIfNull(model, nameof(model)); return collection.DeleteOneAsync( Builders.Filter.Eq(m => m.Id, model.Id), @@ -432,8 +425,7 @@ private Task FindOneOnDBAsync( CancellationToken cancellationToken = default) => AccessToCollectionAsync(async collection => { - if (predicate is null) - throw new ArgumentNullException(nameof(predicate)); + ArgumentNullException.ThrowIfNull(predicate, nameof(predicate)); using var cursor = await collection.FindAsync(predicate, cancellationToken: cancellationToken).ConfigureAwait(false); var model = await cursor.FirstOrDefaultAsync(cancellationToken).ConfigureAwait(false); @@ -441,7 +433,7 @@ private Task FindOneOnDBAsync( if (model == default(TModel)) throw new MongodmEntityNotFoundException("Can't find element"); - logger.RepositoryFoundDocument(Name, DbContext.Options.DbName, model.Id!.ToString()); + logger.RepositoryFoundDocument(Name, DbContext.Options.DbName, model.Id!.ToString()!); return model; }); @@ -454,8 +446,7 @@ private Task ReplaceHelperAsync( CancellationToken cancellationToken) => AccessToCollectionAsync(async collection => { - if (model == null) - throw new ArgumentNullException(nameof(model)); + ArgumentNullException.ThrowIfNull(model, nameof(model)); // Replace on db. if (session == null) @@ -481,7 +472,7 @@ await collection.ReplaceOneAsync( // Reset changed members. ((IAuditable)model).ResetChangedMembers(); - logger.RepositoryReplacedDocument(Name, DbContext.Options.DbName, model.Id!.ToString()); + logger.RepositoryReplacedDocument(Name, DbContext.Options.DbName, model.Id!.ToString()!); }); } } \ No newline at end of file diff --git a/src/MongODM.Core/Repositories/RepositoryRegistry.cs b/src/MongODM.Core/Repositories/RepositoryRegistry.cs index 106f909..6c2a6eb 100644 --- a/src/MongODM.Core/Repositories/RepositoryRegistry.cs +++ b/src/MongODM.Core/Repositories/RepositoryRegistry.cs @@ -26,11 +26,12 @@ public class RepositoryRegistry : IRepositoryRegistry { // Fields. private ILogger logger = default!; - private IReadOnlyDictionary _repositoriesByModelType = default!; + private Dictionary _repositoriesByModelType = default!; // Initializer. public void Initialize(IDbContext dbContext, ILogger logger) { + ArgumentNullException.ThrowIfNull(dbContext, nameof(dbContext)); this.logger = logger ?? throw new ArgumentNullException(nameof(logger)); if (IsInitialized) @@ -59,8 +60,8 @@ public void Initialize(IDbContext dbContext, ILogger logger) //initialize registry _repositoriesByModelType = repos.ToDictionary( - prop => ((IRepository)prop.GetValue(dbContext)).ModelType, - prop => (IRepository)prop.GetValue(dbContext)); + prop => ((IRepository)prop.GetValue(dbContext)!).ModelType, + prop => (IRepository)prop.GetValue(dbContext)!); IsInitialized = true; @@ -78,11 +79,13 @@ public IRepository GetRepositoryByBaseModelType() public IRepository GetRepositoryByHandledModelType(Type modelType) { + ArgumentNullException.ThrowIfNull(modelType, nameof(modelType)); + while (!_repositoriesByModelType.ContainsKey(modelType)) { if (modelType == typeof(object)) throw new InvalidOperationException($"Cant find valid repository for model type {modelType}"); - modelType = modelType.BaseType; + modelType = modelType.BaseType!; } return _repositoriesByModelType[modelType]; diff --git a/src/MongODM.Core/Serialization/Mapping/CustomSerializerMap.cs b/src/MongODM.Core/Serialization/Mapping/CustomSerializerMap.cs index 16cb4e3..dd9845c 100644 --- a/src/MongODM.Core/Serialization/Mapping/CustomSerializerMap.cs +++ b/src/MongODM.Core/Serialization/Mapping/CustomSerializerMap.cs @@ -17,7 +17,7 @@ namespace Etherna.MongODM.Core.Serialization.Mapping { - class CustomSerializerMap : MapBase, ICustomSerializerMapBuilder + internal sealed class CustomSerializerMap : MapBase, ICustomSerializerMapBuilder where TModel : class { // Constructor. diff --git a/src/MongODM.Core/Serialization/Mapping/DiscriminatorRegistry.cs b/src/MongODM.Core/Serialization/Mapping/DiscriminatorRegistry.cs index 6f3708a..01caf27 100644 --- a/src/MongODM.Core/Serialization/Mapping/DiscriminatorRegistry.cs +++ b/src/MongODM.Core/Serialization/Mapping/DiscriminatorRegistry.cs @@ -24,18 +24,19 @@ namespace Etherna.MongODM.Core.Serialization.Mapping { - public class DiscriminatorRegistry : IDiscriminatorRegistry + public class DiscriminatorRegistry : IDiscriminatorRegistry, IDisposable { // Fields. private readonly ReaderWriterLockSlim configLock = new(LockRecursionPolicy.SupportsRecursion); private readonly Dictionary discriminatorConventions = new(); private readonly Dictionary> discriminators = new(); private readonly HashSet discriminatedTypes = new(); + + private bool disposed; private ILogger logger = default!; - private IDbContext dbContext = default!; - // Constructor and initializer. + // Initializer. public void Initialize(IDbContext dbContext, ILogger logger) { if (IsInitialized) @@ -47,6 +48,26 @@ public void Initialize(IDbContext dbContext, ILogger logger) this.logger.DiscriminatorRegistryInitialized(dbContext.Options.DbName); } + + // Dispose. + public void Dispose() + { + Dispose(true); + GC.SuppressFinalize(this); + } + + protected virtual void Dispose(bool disposing) + { + if (disposed) return; + + // Dispose managed resources. + if (disposing) + { + configLock.Dispose(); + } + + disposed = true; + } // Properties. public bool IsInitialized { get; private set; } @@ -55,10 +76,8 @@ public void Initialize(IDbContext dbContext, ILogger logger) public void AddDiscriminator(Type type, BsonValue discriminator) { // Checks. - if (type is null) - throw new ArgumentNullException(nameof(type)); - if (discriminator is null) - throw new ArgumentNullException(nameof(discriminator)); + ArgumentNullException.ThrowIfNull(type, nameof(type)); + ArgumentNullException.ThrowIfNull(discriminator, nameof(discriminator)); var typeInfo = type.GetTypeInfo(); if (typeInfo.IsInterface) @@ -68,16 +87,14 @@ public void AddDiscriminator(Type type, BsonValue discriminator) configLock.EnterWriteLock(); try { - if (!discriminators.TryGetValue(discriminator, out HashSet hashSet)) + if (!discriminators.TryGetValue(discriminator, out HashSet? hashSet)) { hashSet = new HashSet(); discriminators.Add(discriminator, hashSet); } - if (!hashSet.Contains(type)) + if (hashSet.Add(type)) { - hashSet.Add(type); - //mark all base types as discriminated (so we know that it's worth reading a discriminator) for (var baseType = typeInfo.BaseType; baseType != null; baseType = baseType.GetTypeInfo().BaseType) discriminatedTypes.Add(baseType); @@ -91,17 +108,13 @@ public void AddDiscriminator(Type type, BsonValue discriminator) public void AddDiscriminatorConvention(Type type, IDiscriminatorConvention convention) { - if (type is null) - throw new ArgumentNullException(nameof(type)); - if (convention is null) - throw new ArgumentNullException(nameof(convention)); + ArgumentNullException.ThrowIfNull(type, nameof(type)); + ArgumentNullException.ThrowIfNull(convention, nameof(convention)); configLock.EnterWriteLock(); try { - if (!discriminatorConventions.ContainsKey(type)) - discriminatorConventions.Add(type, convention); - else + if (!discriminatorConventions.TryAdd(type, convention)) throw new BsonSerializationException($"There is already a discriminator convention registered for type {type.FullName}."); } finally @@ -127,7 +140,7 @@ public Type LookupActualType(Type nominalType, BsonValue? discriminator) Type? actualType = null; var nominalTypeInfo = nominalType.GetTypeInfo(); - if (discriminators.TryGetValue(discriminator, out HashSet hashSet)) + if (discriminators.TryGetValue(discriminator, out HashSet? hashSet)) { foreach (var type in hashSet) { @@ -157,7 +170,7 @@ public IDiscriminatorConvention LookupDiscriminatorConvention(Type type) configLock.EnterReadLock(); try { - if (discriminatorConventions.TryGetValue(type, out IDiscriminatorConvention convention)) + if (discriminatorConventions.TryGetValue(type, out IDiscriminatorConvention? convention)) return convention; } finally @@ -168,7 +181,7 @@ public IDiscriminatorConvention LookupDiscriminatorConvention(Type type) configLock.EnterWriteLock(); try { - if (!discriminatorConventions.TryGetValue(type, out IDiscriminatorConvention convention)) + if (!discriminatorConventions.TryGetValue(type, out IDiscriminatorConvention? convention)) { var typeInfo = type.GetTypeInfo(); if (type == typeof(object)) @@ -186,7 +199,7 @@ public IDiscriminatorConvention LookupDiscriminatorConvention(Type type) else //type is not typeof(object), or interface { //inherit the discriminator convention from the closest parent that has one - convention = LookupDiscriminatorConvention(typeInfo.BaseType); + convention = LookupDiscriminatorConvention(typeInfo.BaseType!); //register the convention for current type AddDiscriminatorConvention(type, convention); diff --git a/src/MongODM.Core/Serialization/Mapping/ElementRepresentationBase.cs b/src/MongODM.Core/Serialization/Mapping/ElementRepresentationBase.cs index 82025b3..41616ef 100644 --- a/src/MongODM.Core/Serialization/Mapping/ElementRepresentationBase.cs +++ b/src/MongODM.Core/Serialization/Mapping/ElementRepresentationBase.cs @@ -17,7 +17,7 @@ namespace Etherna.MongODM.Core.Serialization.Mapping public abstract class ElementRepresentationBase { // Constructor. - public ElementRepresentationBase(IMemberMap memberMap) + protected ElementRepresentationBase(IMemberMap memberMap) { MemberMap = memberMap; } diff --git a/src/MongODM.Core/Serialization/Mapping/MapRegistry.cs b/src/MongODM.Core/Serialization/Mapping/MapRegistry.cs index 6b61702..42ea182 100644 --- a/src/MongODM.Core/Serialization/Mapping/MapRegistry.cs +++ b/src/MongODM.Core/Serialization/Mapping/MapRegistry.cs @@ -62,8 +62,7 @@ public ICustomSerializerMapBuilder AddCustomSerializerMap( IBsonSerializer customSerializer) where TModel : class => ExecuteConfigAction(() => { - if (customSerializer is null) - throw new ArgumentNullException(nameof(customSerializer)); + ArgumentNullException.ThrowIfNull(customSerializer, nameof(customSerializer)); // Register and return map configuration. var customSerializerMap = new CustomSerializerMap(customSerializer); @@ -75,7 +74,7 @@ public ICustomSerializerMapBuilder AddCustomSerializerMap( public IModelMapBuilder AddModelMap( string activeModelMapSchemaId, Action>? activeModelMapSchemaInitializer = null, - IBsonSerializer? activeCustomSerializer = null) + IBsonSerializer? customSerializer = null) where TModel : class => ExecuteConfigAction(() => { @@ -89,7 +88,7 @@ public IModelMapBuilder AddModelMap( new BsonClassMap(activeModelMapSchemaInitializer ?? (cm => cm.AutoMap())), null, null, - activeCustomSerializer, + customSerializer, modelMap); modelMap.ActiveSchema = schema; @@ -106,17 +105,17 @@ public IModelMapBuilder AddModelMap( public BsonClassMap GetActiveClassMap(Type modelType) { // If a map is registered. - if (_maps.TryGetValue(modelType, out IMap map) && + if (_maps.TryGetValue(modelType, out IMap? map) && map is IModelMap modelMap) return modelMap.ActiveSchema.BsonClassMap; // If we don't have a model map, look for a default classmap, or create it. - if (defaultClassMapsCache.TryGetValue(modelType, out BsonClassMap bcm)) + if (defaultClassMapsCache.TryGetValue(modelType, out BsonClassMap? bcm)) return bcm; var classMapDefinition = typeof(BsonClassMap<>); var classMapType = classMapDefinition.MakeGenericType(modelType); - var classMap = (BsonClassMap)Activator.CreateInstance(classMapType); + var classMap = (BsonClassMap)Activator.CreateInstance(classMapType)!; classMap.AutoMap(); // Register classMap (if doesn't exist) with discriminator. @@ -128,8 +127,7 @@ public BsonClassMap GetActiveClassMap(Type modelType) public BsonElement GetActiveModelMapIdBsonElement(Type modelType) { - if (modelType is null) - throw new ArgumentNullException(nameof(modelType)); + ArgumentNullException.ThrowIfNull(modelType, nameof(modelType)); Freeze(); //needed for initialization @@ -149,6 +147,8 @@ public IEnumerable GetMemberMapsFromMemberInfo(MemberInfo memberInfo public IEnumerable GetMemberMapsWithSameElementPath(IMemberMap memberMap) { + ArgumentNullException.ThrowIfNull(memberMap, nameof(memberMap)); + Freeze(); //needed for initialization return memberMapsByElementPath.TryGetValue(memberMap.MemberMapPath.First().ModelMapSchema.ModelMap, out var elementPathDictionary) && elementPathDictionary.TryGetValue(GetMemberMapElementPath(memberMap), out var samePathMemberMaps) ? @@ -158,13 +158,10 @@ public IEnumerable GetMemberMapsWithSameElementPath(IMemberMap membe public IModelMap GetModelMap(Type modelType) { - if (modelType is null) - throw new ArgumentNullException(nameof(modelType)); - if (!_maps.ContainsKey(modelType)) + ArgumentNullException.ThrowIfNull(modelType, nameof(modelType)); + if (!_maps.TryGetValue(modelType, out var map)) throw new KeyNotFoundException(modelType.Name + " map is missing"); - var map = _maps[modelType]; - if (map is not IModelMap modelMap) throw new InvalidOperationException(modelType.Name + " map is not a model map"); @@ -173,10 +170,9 @@ public IModelMap GetModelMap(Type modelType) public bool TryGetModelMap(Type modelType, out IModelMap? modelMap) { - if (modelType is null) - throw new ArgumentNullException(nameof(modelType)); + ArgumentNullException.ThrowIfNull(modelType, nameof(modelType)); - if (_maps.TryGetValue(modelType, out IMap map) && + if (_maps.TryGetValue(modelType, out IMap? map) && map is IModelMap foundModelMap) { modelMap = foundModelMap; @@ -252,7 +248,7 @@ protected override void FreezeAction() } // Helpers. - private IModelMap CreateNewDefaultModelMap(Type modelType) + private ModelMap CreateNewDefaultModelMap(Type modelType) { // Construct. //model schema @@ -261,13 +257,13 @@ private IModelMap CreateNewDefaultModelMap(Type modelType) var modelMap = (ModelMap)Activator.CreateInstance( modelMapType, - dbContext); //IDbContext dbContext + dbContext)!; //IDbContext dbContext //class map var classMapDefinition = typeof(BsonClassMap<>); var classMapType = classMapDefinition.MakeGenericType(modelType); - var classMap = (BsonClassMap)Activator.CreateInstance(classMapType); + var classMap = (BsonClassMap)Activator.CreateInstance(classMapType)!; //model map var modelMapSchemaDefinition = typeof(ModelMapSchema<>); @@ -286,7 +282,7 @@ private IModelMap CreateNewDefaultModelMap(Type modelType) null!, //IBsonSerializer? customSerializer modelMap //IModelMap modelMap }, - CultureInfo.InvariantCulture); + CultureInfo.InvariantCulture)!; // Set active model map. modelMap.ActiveSchema = activeModelMapSchema; @@ -305,7 +301,7 @@ private void LinkBaseModelMaps() */ var processingModelMaps = new Stack(_maps.Values.OfType()); - while (processingModelMaps.Any()) + while (processingModelMaps.Count != 0) { var modelMap = processingModelMaps.Pop(); @@ -319,7 +315,7 @@ private void LinkBaseModelMaps() continue; // Get base type map, or generate it. - if (!_maps.TryGetValue(baseModelType, out IMap baseMap)) + if (!_maps.TryGetValue(baseModelType, out IMap? baseMap)) { // Create schema instance. baseMap = CreateNewDefaultModelMap(baseModelType); diff --git a/src/MongODM.Core/Serialization/Mapping/MemberMapRenderHelper.cs b/src/MongODM.Core/Serialization/Mapping/MemberMapRenderHelper.cs index 1d74194..f87fb16 100644 --- a/src/MongODM.Core/Serialization/Mapping/MemberMapRenderHelper.cs +++ b/src/MongODM.Core/Serialization/Mapping/MemberMapRenderHelper.cs @@ -14,6 +14,7 @@ using System; using System.Collections.Generic; +using System.Diagnostics.CodeAnalysis; using System.Linq; using System.Text; @@ -21,12 +22,15 @@ namespace Etherna.MongODM.Core.Serialization.Mapping { public static class MemberMapRenderHelper { + [SuppressMessage("Performance", "CA1851:Possible multiple enumerations of \'IEnumerable\' collection")] public static string RenderElementPath( IEnumerable memberMapsPath, bool referToFinalItem, Func undefinedArrayIndexSymbolSelector, Func undefinedDocumentElementSymbolSelector) { + ArgumentNullException.ThrowIfNull(memberMapsPath, nameof(memberMapsPath)); + var sb = new StringBuilder(); foreach (var memberMap in memberMapsPath) @@ -51,6 +55,10 @@ public static string RenderInternalItemElementPath( Func undefinedArrayIndexSymbolSelector, Func undefinedDocumentElementSymbolSelector) { + ArgumentNullException.ThrowIfNull(elementsPath, nameof(elementsPath)); + ArgumentNullException.ThrowIfNull(undefinedArrayIndexSymbolSelector, nameof(undefinedArrayIndexSymbolSelector)); + ArgumentNullException.ThrowIfNull(undefinedDocumentElementSymbolSelector, nameof(undefinedDocumentElementSymbolSelector)); + var sb = new StringBuilder(); foreach (var element in elementsPath) diff --git a/src/MongODM.Core/Serialization/Mapping/ModelMap.cs b/src/MongODM.Core/Serialization/Mapping/ModelMap.cs index 52e77e2..d6f7d2d 100644 --- a/src/MongODM.Core/Serialization/Mapping/ModelMap.cs +++ b/src/MongODM.Core/Serialization/Mapping/ModelMap.cs @@ -16,6 +16,7 @@ using Etherna.MongODM.Core.Serialization.Serializers; using System; using System.Collections.Generic; +using System.Diagnostics.CodeAnalysis; using System.Linq; using System.Threading.Tasks; @@ -113,8 +114,7 @@ internal void InitializeMemberMaps() protected void AddFallbackCustomSerializerHelper(IBsonSerializer fallbackSerializer) => ExecuteConfigAction(() => { - if (fallbackSerializer is null) - throw new ArgumentNullException(nameof(fallbackSerializer)); + ArgumentNullException.ThrowIfNull(fallbackSerializer, nameof(fallbackSerializer)); if (FallbackSerializer is not null) throw new InvalidOperationException("Fallback serializer already setted"); @@ -124,8 +124,7 @@ protected void AddFallbackCustomSerializerHelper(IBsonSerializer fallbackSeriali protected void AddFallbackModelMapSchemaHelper(IModelMapSchema fallbackSchema) => ExecuteConfigAction(() => { - if (fallbackSchema is null) - throw new ArgumentNullException(nameof(fallbackSchema)); + ArgumentNullException.ThrowIfNull(fallbackSchema, nameof(fallbackSchema)); if (FallbackSchema is not null) throw new InvalidOperationException("Fallback model map schema already setted"); @@ -135,8 +134,7 @@ protected void AddFallbackModelMapSchemaHelper(IModelMapSchema fallbackSchema) = protected void AddSecondarySchemaHelper(IModelMapSchema schema) => ExecuteConfigAction(() => { - if (schema is null) - throw new ArgumentNullException(nameof(schema)); + ArgumentNullException.ThrowIfNull(schema, nameof(schema)); // Try to use proxy model generator. schema.TryUseProxyGenerator(DbContext); @@ -154,7 +152,7 @@ protected override void FreezeAction() } // Helpers. - private IMemberMap BuildMemberMap( + private MemberMap BuildMemberMap( BsonMemberMap bsonMemberMap, IModelMapSchema modelMapSchema, IMemberMap? parentMemberMap) @@ -202,7 +200,8 @@ private IMemberMap BuildMemberMap( } } - internal class ModelMap : ModelMap, IModelMapBuilder + [SuppressMessage("Reliability", "CA2000:Dispose objects before losing scope")] + internal sealed class ModelMap : ModelMap, IModelMapBuilder where TModel : class { // Constructor. diff --git a/src/MongODM.Core/Serialization/Mapping/ModelMapSchema.cs b/src/MongODM.Core/Serialization/Mapping/ModelMapSchema.cs index aa02c38..41adbdb 100644 --- a/src/MongODM.Core/Serialization/Mapping/ModelMapSchema.cs +++ b/src/MongODM.Core/Serialization/Mapping/ModelMapSchema.cs @@ -40,6 +40,8 @@ internal protected ModelMapSchema( IBsonSerializer? customSerializer, IModelMap modelMap) { + ArgumentNullException.ThrowIfNull(bsonClassMap, nameof(bsonClassMap)); + ArgumentNullException.ThrowIfNull(modelMap, nameof(modelMap)); if (string.IsNullOrEmpty(id)) throw new ArgumentException($"'{nameof(id)}' cannot be null or empty", nameof(id)); if (!modelMap.ModelType.IsAssignableFrom(bsonClassMap.ClassType)) @@ -70,8 +72,7 @@ public Task FixDeserializedModelAsync(object model) => public void SetBaseModelMapSchema(IModelMapSchema baseModelMapSchema) => ExecuteConfigAction(() => { - if (baseModelMapSchema is null) - throw new ArgumentNullException(nameof(baseModelMapSchema)); + ArgumentNullException.ThrowIfNull(baseModelMapSchema, nameof(baseModelMapSchema)); BaseSchemaId = baseModelMapSchema.Id; BsonClassMap.SetBaseClassMap(baseModelMapSchema.BsonClassMap); @@ -80,8 +81,7 @@ public void SetBaseModelMapSchema(IModelMapSchema baseModelMapSchema) => public void UseProxyGenerator(IDbContext dbContext) => ExecuteConfigAction(() => { - if (dbContext is null) - throw new ArgumentNullException(nameof(dbContext)); + ArgumentNullException.ThrowIfNull(dbContext, nameof(dbContext)); if (ModelMap.ModelType.IsAbstract) throw new InvalidOperationException("Can't generate proxy of an abstract model"); @@ -107,8 +107,7 @@ public void UseProxyGenerator(IDbContext dbContext) => public bool TryUseProxyGenerator(IDbContext dbContext) { - if (dbContext is null) - throw new ArgumentNullException(nameof(dbContext)); + ArgumentNullException.ThrowIfNull(dbContext, nameof(dbContext)); // Verify if can use proxy model. if (ModelMap.ModelType != typeof(object) && @@ -139,7 +138,7 @@ private IBsonSerializer GetDefaultSerializer() { var modelMapSerializerDefinition = typeof(ModelMapSerializer<>); var modelMapSerializerType = modelMapSerializerDefinition.MakeGenericType(ModelMap.ModelType); - return (IBsonSerializer)Activator.CreateInstance(modelMapSerializerType, ModelMap.DbContext); + return (IBsonSerializer)Activator.CreateInstance(modelMapSerializerType, ModelMap.DbContext)!; } } @@ -173,8 +172,7 @@ public async Task FixDeserializedModelAsync(TModel model) protected override async Task FixDeserializedModelHelperAsync( object model) { - if (model is null) - throw new ArgumentNullException(nameof(model)); + ArgumentNullException.ThrowIfNull(model, nameof(model)); return fixDeserializedModelFunc is not null ? (await fixDeserializedModelFunc((TModel)model).ConfigureAwait(false))! : @@ -213,8 +211,7 @@ public async Task FixDeserializedModelAsync(TModel model) protected override async Task FixDeserializedModelHelperAsync( object model) { - if (model is null) - throw new ArgumentNullException(nameof(model)); + ArgumentNullException.ThrowIfNull(model, nameof(model)); return fixDeserializedModelFunc is not null ? (await fixDeserializedModelFunc((TOverrideNominal)model).ConfigureAwait(false))! : diff --git a/src/MongODM.Core/Serialization/Modifiers/CacheSerializerModifier.cs b/src/MongODM.Core/Serialization/Modifiers/CacheSerializerModifier.cs index 881b1a5..dd1e855 100644 --- a/src/MongODM.Core/Serialization/Modifiers/CacheSerializerModifier.cs +++ b/src/MongODM.Core/Serialization/Modifiers/CacheSerializerModifier.cs @@ -21,7 +21,7 @@ namespace Etherna.MongODM.Core.Serialization.Modifiers { - class CacheSerializerModifier : IDisposable + internal sealed class CacheSerializerModifier : IDisposable { // Consts. private const string ModifierKey = "CacheSerializerModifier"; @@ -32,8 +32,7 @@ class CacheSerializerModifier : IDisposable // Constructors and dispose. public CacheSerializerModifier(IExecutionContext context) { - if (context is null) - throw new ArgumentNullException(nameof(context)); + ArgumentNullException.ThrowIfNull(context, nameof(context)); if (context.Items is null) throw new ExecutionContextNotFoundException(); diff --git a/src/MongODM.Core/Serialization/Modifiers/ReferenceSerializerModifier.cs b/src/MongODM.Core/Serialization/Modifiers/ReferenceSerializerModifier.cs index a76f034..36d1bca 100644 --- a/src/MongODM.Core/Serialization/Modifiers/ReferenceSerializerModifier.cs +++ b/src/MongODM.Core/Serialization/Modifiers/ReferenceSerializerModifier.cs @@ -21,7 +21,7 @@ namespace Etherna.MongODM.Core.Serialization.Modifiers { - class ReferenceSerializerModifier : IDisposable + internal sealed class ReferenceSerializerModifier : IDisposable { // Consts. private const string ModifierKey = "ReferenceSerializerModifier"; @@ -32,8 +32,7 @@ class ReferenceSerializerModifier : IDisposable // Constructors and dispose. public ReferenceSerializerModifier(IExecutionContext context) { - if (context is null) - throw new ArgumentNullException(nameof(context)); + ArgumentNullException.ThrowIfNull(context, nameof(context)); if (context.Items is null) throw new ExecutionContextNotFoundException(); @@ -58,8 +57,7 @@ public void Dispose() // Static methods. public static bool IsReadOnlyIdEnabled(IExecutionContext context) { - if (context is null) - throw new ArgumentNullException(nameof(context)); + ArgumentNullException.ThrowIfNull(context, nameof(context)); if (context.Items is null) throw new ExecutionContextNotFoundException(); diff --git a/src/MongODM.Core/Serialization/Providers/ModelMapSerializationProvider.cs b/src/MongODM.Core/Serialization/Providers/ModelMapSerializationProvider.cs index f3b12c1..8b829eb 100644 --- a/src/MongODM.Core/Serialization/Providers/ModelMapSerializationProvider.cs +++ b/src/MongODM.Core/Serialization/Providers/ModelMapSerializationProvider.cs @@ -35,8 +35,7 @@ public ModelMapSerializationProvider(DbContext dbContext) // Methods. public override IBsonSerializer? GetSerializer(Type type, IBsonSerializerRegistry serializerRegistry) { - if (type == null) - throw new ArgumentNullException(nameof(type)); + ArgumentNullException.ThrowIfNull(type, nameof(type)); var typeInfo = type.GetTypeInfo(); if (typeInfo.IsGenericType && typeInfo.ContainsGenericParameters) @@ -51,7 +50,7 @@ public ModelMapSerializationProvider(DbContext dbContext) { var modelMapSerializerDefinition = typeof(ModelMapSerializer<>); var modelMapSerializerType = modelMapSerializerDefinition.MakeGenericType(type); - return (IBsonSerializer)Activator.CreateInstance(modelMapSerializerType, dbContext); + return (IBsonSerializer)Activator.CreateInstance(modelMapSerializerType, dbContext)!; } return null; diff --git a/src/MongODM.Core/Serialization/Serializers/DictionarySerializer.cs b/src/MongODM.Core/Serialization/Serializers/DictionarySerializer.cs index 661cba7..37944b6 100644 --- a/src/MongODM.Core/Serialization/Serializers/DictionarySerializer.cs +++ b/src/MongODM.Core/Serialization/Serializers/DictionarySerializer.cs @@ -26,6 +26,7 @@ public class DictionarySerializer : IChildSerializerConfigurable, IDictionaryRepresentationConfigurable>, IModelMapsHandlingSerializer + where TKey : notnull { // Constructors. public DictionarySerializer() @@ -49,8 +50,7 @@ public DictionarySerializer(DictionaryRepresentation dictionaryRepresentation, I // Public methods. public override void Serialize(BsonSerializationContext context, BsonSerializationArgs args, IDictionary value) { - if (value is null) - throw new ArgumentNullException(nameof(value)); + ArgumentNullException.ThrowIfNull(value, nameof(value)); // Force to exclude enumerable actual type from serialization. args = new BsonSerializationArgs(value.GetType(), true, args.SerializeIdFirst); diff --git a/src/MongODM.Core/Serialization/Serializers/EnumerableSerializer.cs b/src/MongODM.Core/Serialization/Serializers/EnumerableSerializer.cs index da8efc0..c9d2279 100644 --- a/src/MongODM.Core/Serialization/Serializers/EnumerableSerializer.cs +++ b/src/MongODM.Core/Serialization/Serializers/EnumerableSerializer.cs @@ -50,8 +50,7 @@ public EnumerableSerializer(IBsonSerializer itemSerializer) // Public methods. public override void Serialize(BsonSerializationContext context, BsonSerializationArgs args, IEnumerable value) { - if (value is null) - throw new ArgumentNullException(nameof(value)); + ArgumentNullException.ThrowIfNull(value, nameof(value)); // Force to exclude enumerable actual type from serialization. args = new BsonSerializationArgs(value.GetType(), true, args.SerializeIdFirst); @@ -75,8 +74,7 @@ public EnumerableSerializer WithItemSerializer(IBsonSerializer ite // Protected methods. protected override void AddItem(object accumulator, TItem item) { - if (accumulator is null) - throw new ArgumentNullException(nameof(accumulator)); + ArgumentNullException.ThrowIfNull(accumulator, nameof(accumulator)); ((List)accumulator).Add(item); } diff --git a/src/MongODM.Core/Serialization/Serializers/ExtraElementsSerializer.cs b/src/MongODM.Core/Serialization/Serializers/ExtraElementsSerializer.cs index 8ee64c3..1d16ef2 100644 --- a/src/MongODM.Core/Serialization/Serializers/ExtraElementsSerializer.cs +++ b/src/MongODM.Core/Serialization/Serializers/ExtraElementsSerializer.cs @@ -38,8 +38,7 @@ public ExtraElementsSerializer(IDbContext dbContext) // Methods. public override void Serialize(BsonSerializationContext context, BsonSerializationArgs args, object value) { - if (context is null) - throw new ArgumentNullException(nameof(context)); + ArgumentNullException.ThrowIfNull(context, nameof(context)); if (value is IDictionary dictionary) { diff --git a/src/MongODM.Core/Serialization/Serializers/HexToBinaryDataSerializer.cs b/src/MongODM.Core/Serialization/Serializers/HexToBinaryDataSerializer.cs index b02d367..1a3c7fa 100644 --- a/src/MongODM.Core/Serialization/Serializers/HexToBinaryDataSerializer.cs +++ b/src/MongODM.Core/Serialization/Serializers/HexToBinaryDataSerializer.cs @@ -24,8 +24,7 @@ public class HexToBinaryDataSerializer : SerializerBase // Methods. public override string Deserialize(BsonDeserializationContext context, BsonDeserializationArgs args) { - if (context is null) - throw new ArgumentNullException(nameof(context)); + ArgumentNullException.ThrowIfNull(context, nameof(context)); var bsonReader = context.Reader; var bsonType = bsonReader.GetCurrentBsonType(); @@ -47,8 +46,7 @@ public override string Deserialize(BsonDeserializationContext context, BsonDeser public override void Serialize(BsonSerializationContext context, BsonSerializationArgs args, string value) { - if (context is null) - throw new ArgumentNullException(nameof(context)); + ArgumentNullException.ThrowIfNull(context, nameof(context)); if (value == null) { diff --git a/src/MongODM.Core/Serialization/Serializers/ModelMapSerializer.cs b/src/MongODM.Core/Serialization/Serializers/ModelMapSerializer.cs index 91f86c1..caeef61 100644 --- a/src/MongODM.Core/Serialization/Serializers/ModelMapSerializer.cs +++ b/src/MongODM.Core/Serialization/Serializers/ModelMapSerializer.cs @@ -43,8 +43,7 @@ public class ModelMapSerializer : public ModelMapSerializer( IDbContext dbContext) { - if (dbContext is null) - throw new ArgumentNullException(nameof(dbContext)); + ArgumentNullException.ThrowIfNull(dbContext, nameof(dbContext)); this.dbContext = dbContext; } @@ -67,8 +66,7 @@ public IDiscriminatorConvention DiscriminatorConvention // Methods. public override TModel Deserialize(BsonDeserializationContext context, BsonDeserializationArgs args) { - if (context is null) - throw new ArgumentNullException(nameof(context)); + ArgumentNullException.ThrowIfNull(context, nameof(context)); // Check if null. if (context.Reader.CurrentBsonType == BsonType.Null) @@ -169,8 +167,7 @@ public bool GetDocumentId(object document, out object id, out Type idNominalType public override void Serialize(BsonSerializationContext context, BsonSerializationArgs args, TModel value) { - if (context is null) - throw new ArgumentNullException(nameof(context)); + ArgumentNullException.ThrowIfNull(context, nameof(context)); // Serialize null object. if (value == null) diff --git a/src/MongODM.Core/Serialization/Serializers/ReadOnlyDictionarySerializer.cs b/src/MongODM.Core/Serialization/Serializers/ReadOnlyDictionarySerializer.cs index 13b39b2..58245a5 100644 --- a/src/MongODM.Core/Serialization/Serializers/ReadOnlyDictionarySerializer.cs +++ b/src/MongODM.Core/Serialization/Serializers/ReadOnlyDictionarySerializer.cs @@ -26,6 +26,7 @@ public class ReadOnlyDictionarySerializer : IChildSerializerConfigurable, IDictionaryRepresentationConfigurable>, IModelMapsHandlingSerializer + where TKey : notnull { // Constructors. public ReadOnlyDictionarySerializer() @@ -49,8 +50,7 @@ public ReadOnlyDictionarySerializer(DictionaryRepresentation dictionaryRepresent // Public methods. public override void Serialize(BsonSerializationContext context, BsonSerializationArgs args, IReadOnlyDictionary value) { - if (value is null) - throw new ArgumentNullException(nameof(value)); + ArgumentNullException.ThrowIfNull(value, nameof(value)); // Force to exclude enumerable actual type from serialization. args = new BsonSerializationArgs(value.GetType(), true, args.SerializeIdFirst); diff --git a/src/MongODM.Core/Serialization/Serializers/ReferenceSerializer.cs b/src/MongODM.Core/Serialization/Serializers/ReferenceSerializer.cs index cb9f02d..0704346 100644 --- a/src/MongODM.Core/Serialization/Serializers/ReferenceSerializer.cs +++ b/src/MongODM.Core/Serialization/Serializers/ReferenceSerializer.cs @@ -35,7 +35,6 @@ namespace Etherna.MongODM.Core.Serialization.Serializers /// Model Id type public class ReferenceSerializer : SerializerBase, - IBsonSerializer, IDisposable, IReferenceSerializer where TModelBase : class, IEntityModel @@ -53,8 +52,7 @@ public ReferenceSerializer( IDbContext dbContext, Action configure) { - if (configure is null) - throw new ArgumentNullException(nameof(configure)); + ArgumentNullException.ThrowIfNull(configure, nameof(configure)); this.dbContext = dbContext ?? throw new ArgumentNullException(nameof(dbContext)); @@ -77,7 +75,7 @@ protected virtual void Dispose(bool disposing) if (disposing) { configLockAdapters.Dispose(); - Configuration.Dispose(); + _configuration.Dispose(); } disposed = true; @@ -107,8 +105,7 @@ public IDiscriminatorConvention DiscriminatorConvention // Methods. public override TModelBase Deserialize(BsonDeserializationContext context, BsonDeserializationArgs args) { - if (context is null) - throw new ArgumentNullException(nameof(context)); + ArgumentNullException.ThrowIfNull(context, nameof(context)); // Check bson type. var bsonType = context.Reader.GetCurrentBsonType(); @@ -225,8 +222,7 @@ public override TModelBase Deserialize(BsonDeserializationContext context, BsonD public bool GetDocumentId(object document, out object id, out Type idNominalType, out IIdGenerator idGenerator) { - if (document is null) - throw new ArgumentNullException(nameof(document)); + ArgumentNullException.ThrowIfNull(document, nameof(document)); var serializer = Configuration.ModelMaps[document.GetType()].ActiveSchema.BsonClassMap.ToSerializer(); @@ -241,8 +237,7 @@ public bool GetDocumentId(object document, out object id, out Type idNominalType public override void Serialize(BsonSerializationContext context, BsonSerializationArgs args, TModelBase value) { - if (context is null) - throw new ArgumentNullException(nameof(context)); + ArgumentNullException.ThrowIfNull(context, nameof(context)); // Check value type. if (value == null) @@ -279,8 +274,7 @@ public override void Serialize(BsonSerializationContext context, BsonSerializati public void SetDocumentId(object document, object id) { - if (document is null) - throw new ArgumentNullException(nameof(document)); + ArgumentNullException.ThrowIfNull(document, nameof(document)); var serializer = Configuration.ModelMaps[document.GetType()].ActiveSchema.BsonClassMap.ToSerializer(); diff --git a/src/MongODM.Core/Serialization/Serializers/ReferenceSerializerConfiguration.cs b/src/MongODM.Core/Serialization/Serializers/ReferenceSerializerConfiguration.cs index 5a15756..6813d37 100644 --- a/src/MongODM.Core/Serialization/Serializers/ReferenceSerializerConfiguration.cs +++ b/src/MongODM.Core/Serialization/Serializers/ReferenceSerializerConfiguration.cs @@ -78,8 +78,7 @@ public IModelMapBuilder AddModelMap( public BsonElement GetActiveModelMapIdBsonElement(Type modelType) { - if (modelType is null) - throw new ArgumentNullException(nameof(modelType)); + ArgumentNullException.ThrowIfNull(modelType, nameof(modelType)); Freeze(); //needed for initialization @@ -92,14 +91,11 @@ public BsonElement GetActiveModelMapIdBsonElement(Type modelType) public IBsonSerializer? GetSerializer(Type modelType, string? modelMapSchemaId) { - if (modelType is null) - throw new ArgumentNullException(nameof(modelType)); - if (!_modelMaps.ContainsKey(modelType)) + ArgumentNullException.ThrowIfNull(modelType, nameof(modelType)); + if (!_modelMaps.TryGetValue(modelType, out var modelMap)) throw new InvalidOperationException("Can't identify registered schema for type " + modelType.Name); // Find serializer. - var modelMap = _modelMaps[modelType]; - //if a correct model map is identified with its id, use its bson class map serializer if (modelMapSchemaId != null && modelMap.SchemasById.ContainsKey(modelMapSchemaId)) return modelMap.SchemasById[modelMapSchemaId].BsonClassMap.ToSerializer(); @@ -137,7 +133,7 @@ protected override void FreezeAction() } // Helpers - private IModelMap CreateNewDefaultModelMap(Type modelType) + private ModelMap CreateNewDefaultModelMap(Type modelType) { //model schema var modelSchemaDefinition = typeof(ModelMap<>); @@ -145,13 +141,13 @@ private IModelMap CreateNewDefaultModelMap(Type modelType) var modelSchema = (ModelMap)Activator.CreateInstance( modelSchemaType, - dbContext); //IDbContext dbContext + dbContext)!; //IDbContext dbContext //class map var classMapDefinition = typeof(BsonClassMap<>); var classMapType = classMapDefinition.MakeGenericType(modelType); - var classMap = (BsonClassMap)Activator.CreateInstance(classMapType); + var classMap = (BsonClassMap)Activator.CreateInstance(classMapType)!; //model map var modelMapSchemaDefinition = typeof(ModelMapSchema<>); @@ -170,7 +166,7 @@ private IModelMap CreateNewDefaultModelMap(Type modelType) null!, //IBsonSerializer? customSerializer modelSchema //IModelSchema schema }, - CultureInfo.InvariantCulture); + CultureInfo.InvariantCulture)!; // Set active model map. modelSchema.ActiveSchema = activeModelMapSchema; @@ -187,7 +183,7 @@ private void LinkBaseModelMaps() */ var processingModelMaps = new Stack(_modelMaps.Values); - while (processingModelMaps.Any()) + while (processingModelMaps.Count != 0) { var modelMap = processingModelMaps.Pop(); var baseModelType = modelMap.ModelType.BaseType; @@ -197,7 +193,7 @@ private void LinkBaseModelMaps() continue; // Get base type schema, or generate it. - if (!_modelMaps.TryGetValue(baseModelType, out IModelMap baseModelMap)) + if (!_modelMaps.TryGetValue(baseModelType, out IModelMap? baseModelMap)) { // Create schema instance. baseModelMap = CreateNewDefaultModelMap(baseModelType); diff --git a/src/MongODM.Core/Tasks/MigrateDbContextTask.cs b/src/MongODM.Core/Tasks/MigrateDbContextTask.cs index db47087..57f094c 100644 --- a/src/MongODM.Core/Tasks/MigrateDbContextTask.cs +++ b/src/MongODM.Core/Tasks/MigrateDbContextTask.cs @@ -35,7 +35,7 @@ public MigrateDbContextTask( public async Task RunAsync(string dbMigrationOpId, string taskId) where TDbContext : class, IDbContext { - var dbContext = (TDbContext)serviceProvider.GetService(typeof(TDbContext)); + var dbContext = (TDbContext)serviceProvider.GetService(typeof(TDbContext))!; var dbMigrationOp = (DbMigrationOperation)await dbContext.DbOperations.FindOneAsync(dbMigrationOpId).ConfigureAwait(false); var completedWithErrors = false; diff --git a/src/MongODM.Core/Tasks/UpdateDocDependenciesTask.cs b/src/MongODM.Core/Tasks/UpdateDocDependenciesTask.cs index 4907aa7..66af34b 100644 --- a/src/MongODM.Core/Tasks/UpdateDocDependenciesTask.cs +++ b/src/MongODM.Core/Tasks/UpdateDocDependenciesTask.cs @@ -60,19 +60,17 @@ public async Task RunAsync( IEnumerable idMemberMapIdentifiers) where TDbContext : class, IDbContext { - if (idMemberMapIdentifiers is null) - throw new ArgumentNullException(nameof(idMemberMapIdentifiers)); - if (referencedModelId is null) - throw new ArgumentNullException(nameof(referencedModelId)); + ArgumentNullException.ThrowIfNull(idMemberMapIdentifiers, nameof(idMemberMapIdentifiers)); + ArgumentNullException.ThrowIfNull(referencedModelId, nameof(referencedModelId)); - logger.UpdateDocDependenciesTaskStarted(typeof(TDbContext), referencedRepositoryName, referencedModelId.ToString(), idMemberMapIdentifiers); + logger.UpdateDocDependenciesTaskStarted(typeof(TDbContext), referencedRepositoryName, referencedModelId.ToString()!, idMemberMapIdentifiers); // Get data. - var dbContext = (TDbContext)serviceProvider.GetService(typeof(TDbContext)); + var dbContext = (TDbContext)serviceProvider.GetService(typeof(TDbContext))!; using var dbExecutionContext = new DbExecutionContextHandler(dbContext); //run into a db execution context var referencedRepository = dbContext.RepositoryRegistry.Repositories.First(r => r.Name == referencedRepositoryName); - var referencedModel = await referencedRepository.FindOneAsync(referencedModelId); + var referencedModel = await referencedRepository.FindOneAsync(referencedModelId).ConfigureAwait(false); var referencedModelType = dbContext.ProxyGenerator.PurgeProxyType(referencedModel.GetType()); // Recover reference id member maps model's schemas, and all model maps. @@ -108,15 +106,15 @@ public async Task RunAsync( var documentSerializer = idmm.ModelMapSchema.ModelMap.ActiveSchema.Serializer; //use cache - if (!serializedDocumentsCache.ContainsKey(documentSerializer)) + if (!serializedDocumentsCache.TryGetValue(documentSerializer, out BsonDocument? doc)) { - var serializedDocument = new BsonDocument(); - using var bsonWriter = new BsonDocumentWriter(serializedDocument); + doc = new BsonDocument(); + using var bsonWriter = new BsonDocumentWriter(doc); var context = BsonSerializationContext.CreateRoot(bsonWriter); documentSerializer.Serialize(context, referencedModel); - serializedDocumentsCache[documentSerializer] = serializedDocument; + serializedDocumentsCache[documentSerializer] = doc; } - return (idMemberMap: idmm, doc: serializedDocumentsCache[documentSerializer]); + return (idMemberMap: idmm, doc); }) //take one id member map for each generated path. Drop equivalent member maps generated by secondary schemas, but with same path .GroupBy(pair => pair.idMemberMap.RenderElementPath(false, _ => ".$", _ => ".*")) @@ -151,11 +149,11 @@ public async Task RunAsync( var originModelType = repository.ModelType; var originIdType = repository.KeyType; - var result = typeof(UpdateDocDependenciesTask).GetMethod(nameof(FindUpdatableDocumentsIdAsync), BindingFlags.NonPublic | BindingFlags.Static) + var result = typeof(UpdateDocDependenciesTask).GetMethod(nameof(FindUpdatableDocumentsIdAsync), BindingFlags.NonPublic | BindingFlags.Static)! .MakeGenericMethod(originModelType, originIdType) .Invoke(null, new[] { repository, selectedIdMemberMaps, referencedModelId }); - updatableDocumentsIdByRepository.Add(repository, await (Task>)result); + updatableDocumentsIdByRepository.Add(repository, await ((Task>)result!).ConfigureAwait(false)); } // Update models. @@ -170,7 +168,7 @@ public async Task RunAsync( var originModelType = repository.ModelType; var originIdType = repository.KeyType; var findAndUpdateAsyncMethodInfo = typeof(UpdateDocDependenciesTask) - .GetMethod(nameof(FindAndUpdateAsync), BindingFlags.NonPublic | BindingFlags.Static) + .GetMethod(nameof(FindAndUpdateAsync), BindingFlags.NonPublic | BindingFlags.Static)! .MakeGenericMethod(originModelType, originIdType); foreach (var updatableDocumentId in updatableDocumentsIdByRepository[repository]) @@ -189,7 +187,7 @@ public async Task RunAsync( } } - logger.UpdateDocDependenciesTaskEnded(typeof(TDbContext), referencedRepositoryName, referencedModelId.ToString()); + logger.UpdateDocDependenciesTaskEnded(typeof(TDbContext), referencedRepositoryName, referencedModelId.ToString()!); } // Helpers. @@ -271,7 +269,7 @@ private static async Task FindAndUpdateAsync( collection.FindOneAndUpdateAsync( filter, update, - new FindOneAndUpdateOptions { ArrayFilters = arrayFilters })); + new FindOneAndUpdateOptions { ArrayFilters = arrayFilters })).ConfigureAwait(false); return model is not null; } @@ -293,7 +291,7 @@ private static async Task> FindUpdatableDocumentsIdAsync ids = new(); - while (await cursor.MoveNextAsync()) + while (await cursor.MoveNextAsync().ConfigureAwait(false)) ids.AddRange(cursor.Current.Select(m => (object)m.Id!)); return ids; diff --git a/src/MongODM.Core/Utility/DbCache.cs b/src/MongODM.Core/Utility/DbCache.cs index f505049..9e86a91 100644 --- a/src/MongODM.Core/Utility/DbCache.cs +++ b/src/MongODM.Core/Utility/DbCache.cs @@ -35,8 +35,7 @@ public class DbCache : IDbCache // Constructors. public void Initialize(IDbContext dbContext, ILogger logger) { - if (dbContext is null) - throw new ArgumentNullException(nameof(dbContext)); + ArgumentNullException.ThrowIfNull(dbContext, nameof(dbContext)); if (IsInitialized) throw new InvalidOperationException("Instance already initialized"); @@ -78,10 +77,8 @@ public void ClearCache() public void AddModel(object id, TModel model) where TModel : class, IEntityModel { - if (id == null) - throw new ArgumentNullException(nameof(id)); - if (model == null) - throw new ArgumentNullException(nameof(model)); + ArgumentNullException.ThrowIfNull(id, nameof(id)); + ArgumentNullException.ThrowIfNull(model, nameof(model)); if (executionContext.Items is null) throw new InvalidOperationException("Execution context can't have null Items here"); diff --git a/src/MongODM.Core/Utility/DbExecutionContextHandler.cs b/src/MongODM.Core/Utility/DbExecutionContextHandler.cs index 2ca9cc8..f0e3649 100644 --- a/src/MongODM.Core/Utility/DbExecutionContextHandler.cs +++ b/src/MongODM.Core/Utility/DbExecutionContextHandler.cs @@ -64,8 +64,7 @@ public void Dispose() // Static methods. public static IDbContext? TryGetCurrentDbContext(IExecutionContext executionContext) { - if (executionContext is null) - throw new ArgumentNullException(nameof(executionContext)); + ArgumentNullException.ThrowIfNull(executionContext, nameof(executionContext)); if (executionContext.Items is null || !executionContext.Items.ContainsKey(HandlerKey)) diff --git a/src/MongODM.Core/Utility/DbMaintainer.cs b/src/MongODM.Core/Utility/DbMaintainer.cs index 60ee7dd..760ccb0 100644 --- a/src/MongODM.Core/Utility/DbMaintainer.cs +++ b/src/MongODM.Core/Utility/DbMaintainer.cs @@ -80,8 +80,7 @@ public void Initialize(IDbContext dbContext, ILogger logger) */ public void OnUpdatedModel(IAuditable updatedModel) { - if (updatedModel is null) - throw new ArgumentNullException(nameof(updatedModel)); + ArgumentNullException.ThrowIfNull(updatedModel, nameof(updatedModel)); if (updatedModel is not IEntityModel) throw new ArgumentException($"Model is not of type {nameof(IEntityModel)}", nameof(updatedModel)); diff --git a/src/MongODM.Core/Utility/DbMigrationManager.cs b/src/MongODM.Core/Utility/DbMigrationManager.cs index f70f225..98e272e 100644 --- a/src/MongODM.Core/Utility/DbMigrationManager.cs +++ b/src/MongODM.Core/Utility/DbMigrationManager.cs @@ -61,8 +61,7 @@ await dbContext.DbOperations.QueryElementsAsync(elements => public async Task GetMigrationAsync(string migrateOperationId) { - if (migrateOperationId is null) - throw new ArgumentNullException(nameof(migrateOperationId)); + ArgumentNullException.ThrowIfNull(migrateOperationId, nameof(migrateOperationId)); var migrateOp = await dbContext.DbOperations.QueryElementsAsync(elements => elements.OfType() diff --git a/src/MongODM.Core/Utility/FreezableConfig.cs b/src/MongODM.Core/Utility/FreezableConfig.cs index 538ab28..5df6de2 100644 --- a/src/MongODM.Core/Utility/FreezableConfig.cs +++ b/src/MongODM.Core/Utility/FreezableConfig.cs @@ -78,8 +78,7 @@ public void Freeze() // Protected methods. protected void ExecuteConfigAction(Action configAction) { - if (configAction is null) - throw new ArgumentNullException(nameof(configAction)); + ArgumentNullException.ThrowIfNull(configAction, nameof(configAction)); ExecuteConfigAction(() => { @@ -90,8 +89,7 @@ protected void ExecuteConfigAction(Action configAction) protected TReturn ExecuteConfigAction(Func configAction) { - if (configAction is null) - throw new ArgumentNullException(nameof(configAction)); + ArgumentNullException.ThrowIfNull(configAction, nameof(configAction)); configLock.EnterWriteLock(); try diff --git a/src/MongODM.Hangfire/Filters/AsyncLocalContextHangfireFilter.cs b/src/MongODM.Hangfire/Filters/AsyncLocalContextHangfireFilter.cs index 616aae6..8f9f94e 100644 --- a/src/MongODM.Hangfire/Filters/AsyncLocalContextHangfireFilter.cs +++ b/src/MongODM.Hangfire/Filters/AsyncLocalContextHangfireFilter.cs @@ -32,28 +32,26 @@ public AsyncLocalContextHangfireFilter(IAsyncLocalContext asyncLocalContext) } // Properties. - public void OnPerforming(PerformingContext filterContext) + public void OnPerforming(PerformingContext context) { - if (filterContext is null) - throw new ArgumentNullException(nameof(filterContext)); + ArgumentNullException.ThrowIfNull(context, nameof(context)); lock (contextHandlers) { - contextHandlers.Add(filterContext.BackgroundJob.Id, asyncLocalContext.InitAsyncLocalContext()); + contextHandlers.Add(context.BackgroundJob.Id, asyncLocalContext.InitAsyncLocalContext()); } } - public void OnPerformed(PerformedContext filterContext) + public void OnPerformed(PerformedContext context) { - if (filterContext is null) - throw new ArgumentNullException(nameof(filterContext)); + ArgumentNullException.ThrowIfNull(context, nameof(context)); lock (contextHandlers) { - var jobId = filterContext.BackgroundJob.Id; - var context = contextHandlers[jobId]; + var jobId = context.BackgroundJob.Id; + var contextHandler = contextHandlers[jobId]; contextHandlers.Remove(jobId); - context.Dispose(); + contextHandler.Dispose(); } } } diff --git a/src/MongODM.Hangfire/MongODM.Hangfire.csproj b/src/MongODM.Hangfire/MongODM.Hangfire.csproj index a058275..6da8ddd 100644 --- a/src/MongODM.Hangfire/MongODM.Hangfire.csproj +++ b/src/MongODM.Hangfire/MongODM.Hangfire.csproj @@ -1,7 +1,7 @@  - netstandard2.0 + net6.0;net7.0;net8.0 true Etherna.MongODM.HF Etherna SA diff --git a/src/MongODM.Hangfire/Tasks/MigrateDbContextTaskFacade.cs b/src/MongODM.Hangfire/Tasks/MigrateDbContextTaskFacade.cs index 40bc292..788b09c 100644 --- a/src/MongODM.Hangfire/Tasks/MigrateDbContextTaskFacade.cs +++ b/src/MongODM.Hangfire/Tasks/MigrateDbContextTaskFacade.cs @@ -20,7 +20,7 @@ namespace Etherna.MongODM.HF.Tasks { - class MigrateDbContextTaskFacade + internal sealed class MigrateDbContextTaskFacade { // Fields. private readonly IMigrateDbContextTask task; @@ -35,10 +35,10 @@ public MigrateDbContextTaskFacade(IMigrateDbContextTask task) public Task RunAsync(Type dbContextType, string dbMigrationOpId, PerformContext context) { var method = typeof(MigrateDbContextTask).GetMethod( - nameof(MigrateDbContextTask.RunAsync), BindingFlags.Public | BindingFlags.Instance) + nameof(MigrateDbContextTask.RunAsync), BindingFlags.Public | BindingFlags.Instance)! .MakeGenericMethod(dbContextType); - return (Task)method.Invoke(task, new object[] { dbMigrationOpId, context.BackgroundJob.Id }); + return (Task)method.Invoke(task, new object[] { dbMigrationOpId, context.BackgroundJob.Id })!; } } } diff --git a/src/MongODM.Hangfire/Tasks/UpdateDocDependenciesTaskFacade.cs b/src/MongODM.Hangfire/Tasks/UpdateDocDependenciesTaskFacade.cs index 6e7880a..9f245f3 100644 --- a/src/MongODM.Hangfire/Tasks/UpdateDocDependenciesTaskFacade.cs +++ b/src/MongODM.Hangfire/Tasks/UpdateDocDependenciesTaskFacade.cs @@ -20,7 +20,7 @@ namespace Etherna.MongODM.HF.Tasks { - class UpdateDocDependenciesTaskFacade + internal sealed class UpdateDocDependenciesTaskFacade { // Fields. private readonly IUpdateDocDependenciesTask task; @@ -39,7 +39,7 @@ public Task RunAsync( IEnumerable idMemberMapIdentifiers) { var method = typeof(UpdateDocDependenciesTask).GetMethod( - nameof(UpdateDocDependenciesTask.RunAsync), BindingFlags.Public | BindingFlags.Instance) + nameof(UpdateDocDependenciesTask.RunAsync), BindingFlags.Public | BindingFlags.Instance)! .MakeGenericMethod( dbContextType); @@ -48,7 +48,7 @@ public Task RunAsync( referenceRepositoryName, modelId, idMemberMapIdentifiers - }); + })!; } } } diff --git a/src/MongODM/MongODM.csproj b/src/MongODM/MongODM.csproj index e7b70ed..81ef04b 100644 --- a/src/MongODM/MongODM.csproj +++ b/src/MongODM/MongODM.csproj @@ -1,7 +1,7 @@  - net6.0;net7.0 + net6.0;net7.0;net8.0 true Etherna.MongODM Etherna SA diff --git a/test/MongODM.Core.Tests/MongODM.Core.Tests.csproj b/test/MongODM.Core.Tests/MongODM.Core.Tests.csproj index ebe46e6..1c856eb 100644 --- a/test/MongODM.Core.Tests/MongODM.Core.Tests.csproj +++ b/test/MongODM.Core.Tests/MongODM.Core.Tests.csproj @@ -1,7 +1,7 @@  - net7.0 + net8.0 true Etherna.MongODM.Core false