From 60e51e95e9facd31935fe635370fb59a9577d8b0 Mon Sep 17 00:00:00 2001 From: zhenlei520 <wangzhenlei520@gmail.com> Date: Tue, 2 May 2023 16:25:19 +0800 Subject: [PATCH] fix: fix issues-592 and Uniform type conversion method --- .../DefaultTypeConvertProvider.cs | 41 ++++--- .../DefaultTypeConvertProviderTest.cs | 88 +++++++++++++ .../Masa.BuildingBlocks.Data.Tests.csproj | 1 + .../_Imports.cs | 3 + .../IConvertProvider.cs | 9 -- .../Masa.BuildingBlocks.Service.Caller.csproj | 1 - .../DbContextTest.cs | 116 ++++++++++++++++-- .../DefaultTypeAndDefaultValueProviderTest.cs | 85 +++++++++++++ .../Entities/People.cs | 14 +++ .../Infrastructure/CustomDbContext.cs | 2 + .../DefaultTypeAndDefaultValueProvider.cs | 27 ++++ .../Filters/SaveChangeFilter.cs | 36 ++++-- .../Filters/SoftDeleteSaveChangesFilter.cs | 12 +- .../ITypeAndDefaultValueProvider.cs | 18 +++ .../Extensions/DbContextExtensions.cs | 8 +- .../Isolation/IsolationSaveChangesFilter.cs | 8 +- .../Internal/TypeExtensions.cs | 3 +- .../{ => Internal}/DefaultJsonDeserializer.cs | 8 +- .../{ => Internal}/DefaultJsonSerializer.cs | 7 +- ...ib.Extensions.BackgroundJobs.Memory.csproj | 4 +- .../ConvertProvider.cs | 13 -- .../IsolationBuilderExtensions.cs | 1 - .../TenantTest.cs | 32 ----- 23 files changed, 428 insertions(+), 109 deletions(-) create mode 100644 src/BuildingBlocks/Data/Tests/Masa.BuildingBlocks.Data.Tests/DefaultTypeConvertProviderTest.cs delete mode 100644 src/BuildingBlocks/Isolation/Masa.BuildingBlocks.Isolation/IConvertProvider.cs create mode 100644 src/Contrib/Data/Orm/EFCore/Masa.Contrib.Data.EFCore.Tests/DefaultTypeAndDefaultValueProviderTest.cs create mode 100644 src/Contrib/Data/Orm/EFCore/Masa.Contrib.Data.EFCore.Tests/Entities/People.cs create mode 100644 src/Contrib/Data/Orm/EFCore/Masa.Contrib.Data.EFCore/DefaultTypeAndDefaultValueProvider.cs create mode 100644 src/Contrib/Data/Orm/EFCore/Masa.Contrib.Data.EFCore/ITypeAndDefaultValueProvider.cs rename src/Contrib/Data/Serialization/Masa.Contrib.Data.Serialization.Json/{ => Internal}/DefaultJsonDeserializer.cs (64%) rename src/Contrib/Data/Serialization/Masa.Contrib.Data.Serialization.Json/{ => Internal}/DefaultJsonSerializer.cs (63%) delete mode 100644 src/Contrib/Isolation/Masa.Contrib.Isolation.MultiTenant/ConvertProvider.cs diff --git a/src/BuildingBlocks/Data/Masa.BuildingBlocks.Data/TypeConverts/DefaultTypeConvertProvider.cs b/src/BuildingBlocks/Data/Masa.BuildingBlocks.Data/TypeConverts/DefaultTypeConvertProvider.cs index 42bfc475c..fbfb9c1b7 100644 --- a/src/BuildingBlocks/Data/Masa.BuildingBlocks.Data/TypeConverts/DefaultTypeConvertProvider.cs +++ b/src/BuildingBlocks/Data/Masa.BuildingBlocks.Data/TypeConverts/DefaultTypeConvertProvider.cs @@ -15,15 +15,23 @@ public class DefaultTypeConvertProvider : ITypeConvertProvider typeof(DateTime?) }; - private readonly List<Type> _notNeedSerializeTypes = new() + private readonly List<Type> _simpleTypes = new() { - typeof(String), - typeof(Guid), - typeof(DateTime), - typeof(Decimal), - typeof(Guid?), - typeof(DateTime?), - typeof(Decimal?) + typeof(string), + typeof(short?), + typeof(short), + typeof(int), + typeof(int?), + typeof(long), + typeof(long?), + typeof(float), + typeof(float?), + typeof(decimal), + typeof(decimal?), + typeof(double), + typeof(double?), + typeof(bool), + typeof(bool?) }; private readonly IDeserializer? _deserializer; @@ -38,15 +46,20 @@ public class DefaultTypeConvertProvider : ITypeConvertProvider public object? ConvertTo(string value, Type type, IDeserializer? deserializer = null) { - if (_types.Contains(type)) - return TypeDescriptor.GetConverter(type).ConvertFromInvariantString(value)!; + if (value.IsNullOrWhiteSpace()) + return default; + + if (_simpleTypes.Contains(type)) + { + if (type.IsNullableType()) + return Convert.ChangeType(value, Nullable.GetUnderlyingType(type)!); - if (!IsSupportDeserialize(type)) return Convert.ChangeType(value, type); + } + + if (_types.Contains(type)) + return TypeDescriptor.GetConverter(type).ConvertFromInvariantString(value)!; return (deserializer ?? _deserializer)!.Deserialize(value, type); } - - private bool IsSupportDeserialize(Type type) - => !type.IsPrimitive && !_notNeedSerializeTypes.Contains(type); } diff --git a/src/BuildingBlocks/Data/Tests/Masa.BuildingBlocks.Data.Tests/DefaultTypeConvertProviderTest.cs b/src/BuildingBlocks/Data/Tests/Masa.BuildingBlocks.Data.Tests/DefaultTypeConvertProviderTest.cs new file mode 100644 index 000000000..bc2249264 --- /dev/null +++ b/src/BuildingBlocks/Data/Tests/Masa.BuildingBlocks.Data.Tests/DefaultTypeConvertProviderTest.cs @@ -0,0 +1,88 @@ +// Copyright (c) MASA Stack All rights reserved. +// Licensed under the MIT License. See LICENSE.txt in the project root for license information. + +namespace Masa.BuildingBlocks.Data.Tests; + +[TestClass] +public class DefaultTypeConvertProviderTest +{ + [TestMethod] + public void ConvertToByBaseType() + { + var defaultTypeConvertProvider = new DefaultTypeConvertProvider(); + Assert.AreEqual((short)0, defaultTypeConvertProvider.ConvertTo<short>("0")); + Assert.AreEqual((short)0, defaultTypeConvertProvider.ConvertTo<short?>("0")); + Assert.AreEqual(null, defaultTypeConvertProvider.ConvertTo<short?>("")); + Assert.AreEqual(0, defaultTypeConvertProvider.ConvertTo<short>("")); + Assert.AreEqual(0, defaultTypeConvertProvider.ConvertTo<int>("0")); + Assert.AreEqual(0, defaultTypeConvertProvider.ConvertTo<int?>("0")); + Assert.AreEqual(null, defaultTypeConvertProvider.ConvertTo<int?>("")); + Assert.AreEqual(0, defaultTypeConvertProvider.ConvertTo<int>("")); + Assert.AreEqual(0, defaultTypeConvertProvider.ConvertTo<long>("0")); + Assert.AreEqual(0, defaultTypeConvertProvider.ConvertTo<long?>("0")); + Assert.AreEqual(null, defaultTypeConvertProvider.ConvertTo<long?>("")); + Assert.AreEqual(0, defaultTypeConvertProvider.ConvertTo<long>("")); + Assert.AreEqual(0, defaultTypeConvertProvider.ConvertTo<float>("0")); + Assert.AreEqual((float)0, defaultTypeConvertProvider.ConvertTo<float?>("0")); + Assert.AreEqual(0, defaultTypeConvertProvider.ConvertTo<float>("")); + Assert.AreEqual(null, defaultTypeConvertProvider.ConvertTo<float?>("")); + Assert.AreEqual(0, defaultTypeConvertProvider.ConvertTo<decimal>("0")); + Assert.AreEqual(0, defaultTypeConvertProvider.ConvertTo<decimal?>("0")); + Assert.AreEqual(0, defaultTypeConvertProvider.ConvertTo<decimal>("")); + Assert.AreEqual(null, defaultTypeConvertProvider.ConvertTo<decimal?>("")); + Assert.AreEqual(0, defaultTypeConvertProvider.ConvertTo<double>("0")); + Assert.AreEqual((double)0, defaultTypeConvertProvider.ConvertTo<double?>("0")); + Assert.AreEqual(0, defaultTypeConvertProvider.ConvertTo<double>("")); + Assert.AreEqual(null, defaultTypeConvertProvider.ConvertTo<double?>("")); + Assert.AreEqual(default, + defaultTypeConvertProvider.ConvertTo<DateTime>(default(DateTime).ToString(CultureInfo.InvariantCulture))); + Assert.AreEqual(default(DateTime), + defaultTypeConvertProvider.ConvertTo<DateTime?>(default(DateTime).ToString(CultureInfo.InvariantCulture))); + Assert.AreEqual(null, defaultTypeConvertProvider.ConvertTo<DateTime?>("")); + Assert.AreEqual(default, defaultTypeConvertProvider.ConvertTo<DateTime>("")); + Assert.AreEqual(null, defaultTypeConvertProvider.ConvertTo<string?>("")); + Assert.AreEqual(null, defaultTypeConvertProvider.ConvertTo<string>("")); + Assert.AreEqual(bool.Parse("False"), defaultTypeConvertProvider.ConvertTo<bool>("False")); + Assert.AreEqual(bool.Parse("False"), defaultTypeConvertProvider.ConvertTo<bool?>("False")); + Assert.AreEqual(false, defaultTypeConvertProvider.ConvertTo<bool>("")); + Assert.AreEqual(null, defaultTypeConvertProvider.ConvertTo<bool?>("")); + + var guid = Guid.NewGuid(); + + Assert.AreEqual(guid, defaultTypeConvertProvider.ConvertTo<Guid>(guid.ToString())); + Assert.AreEqual(guid, defaultTypeConvertProvider.ConvertTo<Guid?>(guid.ToString())); + Assert.AreEqual(Guid.Empty, defaultTypeConvertProvider.ConvertTo<Guid>("")); + Assert.AreEqual(null, defaultTypeConvertProvider.ConvertTo<Guid?>("")); + + var date = DateTime.UtcNow; + + Assert.AreEqual(date.ToString(CultureInfo.InvariantCulture), + defaultTypeConvertProvider.ConvertTo<DateTime>(date.ToString(CultureInfo.InvariantCulture)) + .ToString(CultureInfo.InvariantCulture)); + + var convertToValue = defaultTypeConvertProvider.ConvertTo<DateTime?>(date.ToString(CultureInfo.InvariantCulture)); + Assert.IsNotNull(convertToValue); + Assert.AreEqual(date.ToString(CultureInfo.InvariantCulture), ((DateTime)convertToValue).ToString(CultureInfo.InvariantCulture)); + Assert.AreEqual(default(DateTime), defaultTypeConvertProvider.ConvertTo<DateTime>("")); + Assert.AreEqual(null, defaultTypeConvertProvider.ConvertTo<DateTime?>("")); + } + + [TestMethod] + public void ConvertToByComplexType() + { + var list = new List<int>() + { + 1, + 3, + 5 + }; + var value = list.ToJson(); + var defaultTypeConvertProvider = new DefaultTypeConvertProvider(); + var actualValue = defaultTypeConvertProvider.ConvertTo<List<int>>(value, new DefaultJsonDeserializer()); + Assert.IsNotNull(actualValue); + Assert.AreEqual(3, actualValue.Count); + Assert.AreEqual(1, actualValue[0]); + Assert.AreEqual(3, actualValue[1]); + Assert.AreEqual(5, actualValue[2]); + } +} diff --git a/src/BuildingBlocks/Data/Tests/Masa.BuildingBlocks.Data.Tests/Masa.BuildingBlocks.Data.Tests.csproj b/src/BuildingBlocks/Data/Tests/Masa.BuildingBlocks.Data.Tests/Masa.BuildingBlocks.Data.Tests.csproj index bedef2897..d5afe2111 100644 --- a/src/BuildingBlocks/Data/Tests/Masa.BuildingBlocks.Data.Tests/Masa.BuildingBlocks.Data.Tests.csproj +++ b/src/BuildingBlocks/Data/Tests/Masa.BuildingBlocks.Data.Tests/Masa.BuildingBlocks.Data.Tests.csproj @@ -22,6 +22,7 @@ </ItemGroup> <ItemGroup> + <ProjectReference Include="..\..\..\..\Contrib\Extensions\Masa.Contrib.Extensions.BackgroundJobs.Memory\Masa.Contrib.Extensions.BackgroundJobs.Memory.csproj" /> <ProjectReference Include="..\..\Masa.BuildingBlocks.Data\Masa.BuildingBlocks.Data.csproj" /> </ItemGroup> diff --git a/src/BuildingBlocks/Data/Tests/Masa.BuildingBlocks.Data.Tests/_Imports.cs b/src/BuildingBlocks/Data/Tests/Masa.BuildingBlocks.Data.Tests/_Imports.cs index b18d87d12..e787bd452 100644 --- a/src/BuildingBlocks/Data/Tests/Masa.BuildingBlocks.Data.Tests/_Imports.cs +++ b/src/BuildingBlocks/Data/Tests/Masa.BuildingBlocks.Data.Tests/_Imports.cs @@ -2,4 +2,7 @@ // Licensed under the MIT License. See LICENSE.txt in the project root for license information. global using Masa.BuildingBlocks.Data.Tests.Infrastructure; +global using Masa.Contrib.Data.Serialization.Json; global using Microsoft.VisualStudio.TestTools.UnitTesting; +global using System.Globalization; +global using DateTime = System.DateTime; diff --git a/src/BuildingBlocks/Isolation/Masa.BuildingBlocks.Isolation/IConvertProvider.cs b/src/BuildingBlocks/Isolation/Masa.BuildingBlocks.Isolation/IConvertProvider.cs deleted file mode 100644 index f9aed3942..000000000 --- a/src/BuildingBlocks/Isolation/Masa.BuildingBlocks.Isolation/IConvertProvider.cs +++ /dev/null @@ -1,9 +0,0 @@ -// Copyright (c) MASA Stack All rights reserved. -// Licensed under the MIT License. See LICENSE.txt in the project root for license information. - -namespace Masa.BuildingBlocks.Isolation; - -public interface IConvertProvider -{ - object ChangeType(string value, Type conversionType); -} diff --git a/src/BuildingBlocks/Service/Masa.BuildingBlocks.Service.Caller/Masa.BuildingBlocks.Service.Caller.csproj b/src/BuildingBlocks/Service/Masa.BuildingBlocks.Service.Caller/Masa.BuildingBlocks.Service.Caller.csproj index b2fb333ba..3ee1c943e 100644 --- a/src/BuildingBlocks/Service/Masa.BuildingBlocks.Service.Caller/Masa.BuildingBlocks.Service.Caller.csproj +++ b/src/BuildingBlocks/Service/Masa.BuildingBlocks.Service.Caller/Masa.BuildingBlocks.Service.Caller.csproj @@ -12,7 +12,6 @@ </ItemGroup> <ItemGroup> - <ProjectReference Include="..\..\Data\Masa.BuildingBlocks.Data.Contracts\Masa.BuildingBlocks.Data.Contracts.csproj" /> <ProjectReference Include="..\..\Data\Masa.BuildingBlocks.Data.Contracts\Masa.BuildingBlocks.Data.Contracts.csproj" /> <ProjectReference Include="..\..\Data\Masa.BuildingBlocks.Data\Masa.BuildingBlocks.Data.csproj" /> <ProjectReference Include="..\..\Exception\Masa.BuildingBlocks.Exceptions\Masa.BuildingBlocks.Exceptions.csproj" /> diff --git a/src/Contrib/Data/Orm/EFCore/Masa.Contrib.Data.EFCore.Tests/DbContextTest.cs b/src/Contrib/Data/Orm/EFCore/Masa.Contrib.Data.EFCore.Tests/DbContextTest.cs index 270317d87..49217e8b1 100644 --- a/src/Contrib/Data/Orm/EFCore/Masa.Contrib.Data.EFCore.Tests/DbContextTest.cs +++ b/src/Contrib/Data/Orm/EFCore/Masa.Contrib.Data.EFCore.Tests/DbContextTest.cs @@ -52,7 +52,10 @@ public void TestDbContext4() [TestMethod] public void TestDbContext5() { - Services.Configure<AppConfigOptions>(options => { options.DbConnectionString = MemoryConnectionString; }); + Services.Configure<AppConfigOptions>(options => + { + options.DbConnectionString = MemoryConnectionString; + }); var dbContext = CreateDbContext<CustomDbContext5>(null); var student = GenerateStudent(); dbContext.Set<Student>().Add(student); @@ -76,7 +79,10 @@ public void TestDbContext6() [TestMethod] public void TestDbContext7() { - Services.Configure<AppConfigOptions>(options => { options.DbConnectionString = MemoryConnectionString; }); + Services.Configure<AppConfigOptions>(options => + { + options.DbConnectionString = MemoryConnectionString; + }); var dbContext = CreateDbContext<CustomDbContext7>(null); var student = GenerateStudent(); dbContext.Set<Student>().Add(student); @@ -287,7 +293,10 @@ public async Task TestModifyConnectionString() IServiceProvider serviceProvider = default!; var dbContext = - await CreateDbContextAsync<CustomDbContext>(optionsBuilder => { optionsBuilder.UseSqlite(); }, sp => serviceProvider = sp); + await CreateDbContextAsync<CustomDbContext>(optionsBuilder => + { + optionsBuilder.UseSqlite(); + }, sp => serviceProvider = sp); var connectionStringProvider = serviceProvider.GetService<IConnectionStringProvider>(); Assert.IsNotNull(connectionStringProvider); @@ -338,20 +347,32 @@ public async Task TestUseConfigurationAndSpecify() .Build(); Services.AddSingleton<IConfiguration>(configuration); - await CreateDbContextAsync<CustomDbContext>(optionsBuilder => { optionsBuilder.UseSqlite(); }); + await CreateDbContextAsync<CustomDbContext>(optionsBuilder => + { + optionsBuilder.UseSqlite(); + }); await Assert.ThrowsExceptionAsync<ArgumentException>(async () => { - await CreateDbContextAsync<CustomDbContext2>(optionsBuilder => { optionsBuilder.UseSqlite(SqliteConnectionString); }); + await CreateDbContextAsync<CustomDbContext2>(optionsBuilder => + { + optionsBuilder.UseSqlite(SqliteConnectionString); + }); }); } [TestMethod] public async Task TestAddMultiDbContextAsync() { - Services.AddMasaDbContext<CustomDbContext>(dbContextBuilder => { dbContextBuilder.UseInMemoryDatabase(MemoryConnectionString); }); + Services.AddMasaDbContext<CustomDbContext>(dbContextBuilder => + { + dbContextBuilder.UseInMemoryDatabase(MemoryConnectionString); + }); IServiceProvider serviceProvider = default!; var customDbContext2 = await CreateDbContextAsync<CustomDbContext2>( - dbContextBuilder => { dbContextBuilder.UseInMemoryDatabase(MemoryConnectionString); }, sp => serviceProvider = sp); + dbContextBuilder => + { + dbContextBuilder.UseInMemoryDatabase(MemoryConnectionString); + }, sp => serviceProvider = sp); var customDbContext = serviceProvider.GetService<CustomDbContext>(); Assert.IsNotNull(customDbContext); @@ -572,6 +593,76 @@ public async Task TestAddOrUpdateOrDeleteWhenUserIdIsIntAsyncBySpecifyUserIdAndT Assert.AreNotEqual(inputModificationTime.AddDays(2), modificationTimeByUpdate); } + [TestMethod] + public async Task TestAddOrUpdateOrDeleteWhenUserIdIsStringAsync() + { + Services.Configure<AuditEntityOptions>(options => options.UserIdType = typeof(string)); + + var creator = "admin"; + var customUserContext = new CustomUserContext(creator); + Services.AddSingleton<IUserContext>(customUserContext); + + var connectionString = MemoryConnectionString; + var dbContext = await CreateDbContextAsync<CustomDbContext>(dbContextBuilder => + { + dbContextBuilder + .UseInMemoryDatabase(connectionString) + .UseQueryTrackingBehavior(QueryTrackingBehavior.TrackAll) + .UseFilter(); + }); + Assert.IsNotNull(dbContext); + await dbContext.Set<People2>().AddAsync(new People2() + { + Name = "masa" + }); + await dbContext.SaveChangesAsync(); + + var people = await dbContext.Set<People2>().FirstOrDefaultAsync(); + Assert.IsNotNull(people); + Assert.AreEqual(creator, people.Creator); + Assert.AreEqual(creator, people.Modifier); + } + + [TestMethod] + public async Task TestAddOrUpdateOrDeleteWhenUserIdIsGuidAsync() + { + Services.Configure<AuditEntityOptions>(options => options.UserIdType = typeof(Guid)); + + var customUserContext = new CustomUserContext(""); + Services.AddSingleton<IUserContext>(customUserContext); + + var connectionString = MemoryConnectionString; + var dbContext = await CreateDbContextAsync<CustomDbContext>(dbContextBuilder => + { + dbContextBuilder + .UseInMemoryDatabase(connectionString) + .UseQueryTrackingBehavior(QueryTrackingBehavior.TrackAll) + .UseFilter(); + }); + Assert.IsNotNull(dbContext); + await dbContext.Set<People>().AddAsync(new People() + { + Name = "masa" + }); + await dbContext.SaveChangesAsync(); + + var people = await dbContext.Set<People>().AsTracking().FirstOrDefaultAsync(); + Assert.IsNotNull(people); + Assert.AreEqual(null, people.Creator); + Assert.AreEqual(null, people.Modifier); + + var creator = Guid.NewGuid(); + customUserContext.SetUserId(creator.ToString()); + + dbContext.Set<People>().Update(people); + await dbContext.SaveChangesAsync(); + + var peopleByUpdate = await dbContext.Set<People>().AsTracking().FirstOrDefaultAsync(); + Assert.IsNotNull(peopleByUpdate); + Assert.AreEqual(null, peopleByUpdate.Creator); + Assert.AreEqual(creator, peopleByUpdate.Modifier); + } + #endregion #region Test Model Mapping @@ -579,7 +670,10 @@ public async Task TestAddOrUpdateOrDeleteWhenUserIdIsIntAsyncBySpecifyUserIdAndT [TestMethod] public void TestCustomTableName() { - var dbContext = CreateDbContext<CustomDbContext>(dbContext => { dbContext.UseInMemoryDatabase(MemoryConnectionString); }); + var dbContext = CreateDbContext<CustomDbContext>(dbContext => + { + dbContext.UseInMemoryDatabase(MemoryConnectionString); + }); var entityTableName = dbContext.Model.FindEntityType(typeof(Student))?.GetTableName(); Assert.AreEqual("masa_students", entityTableName); @@ -592,7 +686,10 @@ public void TestCustomTableName() [TestMethod] public void TestQueryTrackingBehaviorByDefault() { - var dbContext = CreateDbContext<CustomDbContext>(dbContext => { dbContext.UseInMemoryDatabase(MemoryConnectionString); }); + var dbContext = CreateDbContext<CustomDbContext>(dbContext => + { + dbContext.UseInMemoryDatabase(MemoryConnectionString); + }); Assert.AreEqual(QueryTrackingBehavior.NoTracking, dbContext.ChangeTracker.QueryTrackingBehavior); } @@ -628,4 +725,5 @@ public void TestQueryTrackingBehaviorByUseQueryTrackingBehavior() } #endregion + } diff --git a/src/Contrib/Data/Orm/EFCore/Masa.Contrib.Data.EFCore.Tests/DefaultTypeAndDefaultValueProviderTest.cs b/src/Contrib/Data/Orm/EFCore/Masa.Contrib.Data.EFCore.Tests/DefaultTypeAndDefaultValueProviderTest.cs new file mode 100644 index 000000000..6b7ce8d63 --- /dev/null +++ b/src/Contrib/Data/Orm/EFCore/Masa.Contrib.Data.EFCore.Tests/DefaultTypeAndDefaultValueProviderTest.cs @@ -0,0 +1,85 @@ +// Copyright (c) MASA Stack All rights reserved. +// Licensed under the MIT License. See LICENSE.txt in the project root for license information. + +namespace Masa.Contrib.Data.EFCore.Tests; + +[TestClass] +public class DefaultTypeAndDefaultValueProviderTest +{ + [TestMethod] + public void TestDefaultValues() + { + var defaultValueProvider = new DefaultTypeAndDefaultValueProvider(); + defaultValueProvider.TryAdd(typeof(short)); + defaultValueProvider.TryAdd(typeof(short?)); + defaultValueProvider.TryAdd(typeof(int)); + defaultValueProvider.TryAdd(typeof(int?)); + defaultValueProvider.TryAdd(typeof(long)); + defaultValueProvider.TryAdd(typeof(long?)); + defaultValueProvider.TryAdd(typeof(float)); + defaultValueProvider.TryAdd(typeof(float?)); + defaultValueProvider.TryAdd(typeof(decimal)); + defaultValueProvider.TryAdd(typeof(decimal?)); + defaultValueProvider.TryAdd(typeof(double)); + defaultValueProvider.TryAdd(typeof(double?)); + defaultValueProvider.TryAdd(typeof(Guid)); + defaultValueProvider.TryAdd(typeof(Guid?)); + defaultValueProvider.TryAdd(typeof(DateTime)); + defaultValueProvider.TryAdd(typeof(DateTime?)); + defaultValueProvider.TryAdd(typeof(string)); + defaultValueProvider.TryAdd(typeof(bool)); + defaultValueProvider.TryAdd(typeof(bool?)); + + Assert.AreEqual(true, defaultValueProvider.TryGet(typeof(short), out var defaultValue)); + Assert.AreEqual("0", defaultValue); + + Assert.AreEqual(true, defaultValueProvider.TryGet(typeof(short?), out defaultValue)); + Assert.AreEqual(null, defaultValue); + + Assert.AreEqual(true, defaultValueProvider.TryGet(typeof(int), out defaultValue)); + Assert.AreEqual("0", defaultValue); + + Assert.AreEqual(true, defaultValueProvider.TryGet(typeof(int?), out defaultValue)); + Assert.AreEqual(null, defaultValue); + + Assert.AreEqual(true, defaultValueProvider.TryGet(typeof(long), out defaultValue)); + Assert.AreEqual("0", defaultValue); + + Assert.AreEqual(true, defaultValueProvider.TryGet(typeof(long?), out defaultValue)); + Assert.AreEqual(null, defaultValue); + + Assert.AreEqual(true, defaultValueProvider.TryGet(typeof(float), out defaultValue)); + Assert.AreEqual("0", defaultValue); + + Assert.AreEqual(true, defaultValueProvider.TryGet(typeof(float?), out defaultValue)); + Assert.AreEqual(null, defaultValue); + + Assert.AreEqual(true, defaultValueProvider.TryGet(typeof(decimal), out defaultValue)); + Assert.AreEqual("0", defaultValue); + + Assert.AreEqual(true, defaultValueProvider.TryGet(typeof(decimal?), out defaultValue)); + Assert.AreEqual(null, defaultValue); + + Assert.AreEqual(true, defaultValueProvider.TryGet(typeof(double), out defaultValue)); + Assert.AreEqual("0", defaultValue); + + Assert.AreEqual(true, defaultValueProvider.TryGet(typeof(double?), out defaultValue)); + Assert.AreEqual(null, defaultValue); + + Assert.AreEqual(true, defaultValueProvider.TryGet(typeof(Guid), out defaultValue)); + Assert.AreEqual(Guid.Empty.ToString(), defaultValue); + + Assert.AreEqual(true, defaultValueProvider.TryGet(typeof(Guid?), out defaultValue)); + Assert.AreEqual(null, defaultValue); + + Assert.AreEqual(true, defaultValueProvider.TryGet(typeof(string), out defaultValue)); + Assert.AreEqual(null, defaultValue); + + Assert.AreEqual(true, defaultValueProvider.TryGet(typeof(bool), out defaultValue)); + Assert.AreEqual(default(bool).ToString(), defaultValue); + + Assert.AreEqual(true, defaultValueProvider.TryGet(typeof(bool?), out defaultValue)); + Assert.AreEqual(null, defaultValue); + + } +} diff --git a/src/Contrib/Data/Orm/EFCore/Masa.Contrib.Data.EFCore.Tests/Entities/People.cs b/src/Contrib/Data/Orm/EFCore/Masa.Contrib.Data.EFCore.Tests/Entities/People.cs new file mode 100644 index 000000000..b8b3d7c92 --- /dev/null +++ b/src/Contrib/Data/Orm/EFCore/Masa.Contrib.Data.EFCore.Tests/Entities/People.cs @@ -0,0 +1,14 @@ +// Copyright (c) MASA Stack All rights reserved. +// Licensed under the MIT License. See LICENSE.txt in the project root for license information. + +namespace Masa.Contrib.Data.EFCore.Tests.Entities; + +public class People : FullAggregateRoot<Guid, Guid?> +{ + public string Name { get; set; } +} + +public class People2 : FullAggregateRoot<Guid, string?> +{ + public string Name { get; set; } +} diff --git a/src/Contrib/Data/Orm/EFCore/Masa.Contrib.Data.EFCore.Tests/Infrastructure/CustomDbContext.cs b/src/Contrib/Data/Orm/EFCore/Masa.Contrib.Data.EFCore.Tests/Infrastructure/CustomDbContext.cs index 9928a351d..b06d41041 100644 --- a/src/Contrib/Data/Orm/EFCore/Masa.Contrib.Data.EFCore.Tests/Infrastructure/CustomDbContext.cs +++ b/src/Contrib/Data/Orm/EFCore/Masa.Contrib.Data.EFCore.Tests/Infrastructure/CustomDbContext.cs @@ -20,6 +20,8 @@ protected override void OnModelCreatingExecuting(ModelBuilder modelBuilder) { modelBuilder.InitializeStudentConfiguration(); modelBuilder.Entity<User>(); + modelBuilder.Entity<People>(); + modelBuilder.Entity<People2>(); } } diff --git a/src/Contrib/Data/Orm/EFCore/Masa.Contrib.Data.EFCore/DefaultTypeAndDefaultValueProvider.cs b/src/Contrib/Data/Orm/EFCore/Masa.Contrib.Data.EFCore/DefaultTypeAndDefaultValueProvider.cs new file mode 100644 index 000000000..f1481f4d9 --- /dev/null +++ b/src/Contrib/Data/Orm/EFCore/Masa.Contrib.Data.EFCore/DefaultTypeAndDefaultValueProvider.cs @@ -0,0 +1,27 @@ +// Copyright (c) MASA Stack All rights reserved. +// Licensed under the MIT License. See LICENSE.txt in the project root for license information. + +// ReSharper disable once CheckNamespace + +namespace Microsoft.EntityFrameworkCore; + +public class DefaultTypeAndDefaultValueProvider : ITypeAndDefaultValueProvider +{ + private readonly MemoryCache<Type, string?> _typeAndDefaultValues; + + public DefaultTypeAndDefaultValueProvider() + { + _typeAndDefaultValues = new(); + _typeAndDefaultValues.AddOrUpdate(typeof(string), _ => null); + } + + public bool TryAdd(Type type) + { + return _typeAndDefaultValues.TryAdd(type, t => Activator.CreateInstance(t)?.ToString()); + } + + public bool TryGet(Type type, [NotNullWhen(true)] out string? defaultValue) + { + return _typeAndDefaultValues.TryGet(type, out defaultValue); + } +} diff --git a/src/Contrib/Data/Orm/EFCore/Masa.Contrib.Data.EFCore/Filters/SaveChangeFilter.cs b/src/Contrib/Data/Orm/EFCore/Masa.Contrib.Data.EFCore/Filters/SaveChangeFilter.cs index 065f6ec26..a97ed8b30 100644 --- a/src/Contrib/Data/Orm/EFCore/Masa.Contrib.Data.EFCore/Filters/SaveChangeFilter.cs +++ b/src/Contrib/Data/Orm/EFCore/Masa.Contrib.Data.EFCore/Filters/SaveChangeFilter.cs @@ -10,13 +10,21 @@ public class SaveChangeFilter<TDbContext, TUserId> : ISaveChangesFilter<TDbConte { private readonly Type _userIdType; private readonly IUserContext? _userContext; + private readonly ITypeAndDefaultValueProvider _typeAndDefaultValueProvider; + private readonly ITypeConvertProvider _typeConvertProvider; - public SaveChangeFilter(IUserContext? userContext = null) + public SaveChangeFilter( + IUserContext? userContext = null, + ITypeAndDefaultValueProvider? typeAndDefaultValueProvider = null, + ITypeConvertProvider? typeConvertProvider = null) { _userIdType = typeof(TUserId); _userContext = userContext; - Masa.Contrib.Data.EFCore.TypeExtensions.TypeAndDefaultValues.TryAdd(_userIdType, type => Activator.CreateInstance(type)?.ToString()); - Masa.Contrib.Data.EFCore.TypeExtensions.TypeAndDefaultValues.TryAdd(typeof(DateTime), type => Activator.CreateInstance(type)?.ToString()); + _typeAndDefaultValueProvider = typeAndDefaultValueProvider ?? new DefaultTypeAndDefaultValueProvider(); + _typeConvertProvider = typeConvertProvider ?? new DefaultTypeConvertProvider(); + + _typeAndDefaultValueProvider.TryAdd(_userIdType); + _typeAndDefaultValueProvider.TryAdd(typeof(DateTime)); } public void OnExecuting(ChangeTracker changeTracker) @@ -25,8 +33,8 @@ public void OnExecuting(ChangeTracker changeTracker) var userId = GetUserId(_userContext?.UserId); - var defaultUserId = Masa.Contrib.Data.EFCore.TypeExtensions.TypeAndDefaultValues[_userIdType]; - var defaultDateTime = Masa.Contrib.Data.EFCore.TypeExtensions.TypeAndDefaultValues[typeof(DateTime)]; + _typeAndDefaultValueProvider.TryGet(_userIdType, out string? defaultUserId); + _typeAndDefaultValueProvider.TryGet(typeof(DateTime), out string? defaultDateTime); foreach (var entity in changeTracker.Entries() .Where(entry => entry.State == EntityState.Added || entry.State == EntityState.Modified)) @@ -71,26 +79,30 @@ private static void AuditEntityHandlerByAdded(EntityEntry entity, object? userId if (IsDefault(entity.CurrentValues[nameof(IAuditEntity<TUserId>.CreationTime)], defaultDateTime)) { - entity.CurrentValues[nameof(IAuditEntity<TUserId>.CreationTime)] = DateTime.UtcNow; //The current time to change to localization after waiting for localization + entity.CurrentValues[nameof(IAuditEntity<TUserId>.CreationTime)] = + DateTime.UtcNow; //The current time to change to localization after waiting for localization } if (IsDefault(entity.CurrentValues[nameof(IAuditEntity<TUserId>.ModificationTime)], defaultDateTime)) { - entity.CurrentValues[nameof(IAuditEntity<TUserId>.ModificationTime)] = DateTime.UtcNow; //The current time to change to localization after waiting for localization + entity.CurrentValues[nameof(IAuditEntity<TUserId>.ModificationTime)] = + DateTime.UtcNow; //The current time to change to localization after waiting for localization } } private static bool IsDefault(object? value, string? defaultValue) => value == null || value.ToString() == defaultValue; + /// <summary> + /// Get the current user id + /// Does not consider user id as DateTime type + /// </summary> + /// <returns></returns> private object? GetUserId(string? userId) { - if (userId == null) + if (string.IsNullOrWhiteSpace(userId)) return null; - if (_userIdType == typeof(Guid)) - return Guid.Parse(userId); - - return Convert.ChangeType(userId, _userIdType); + return _typeConvertProvider.ConvertTo(userId, _userIdType); } } diff --git a/src/Contrib/Data/Orm/EFCore/Masa.Contrib.Data.EFCore/Filters/SoftDeleteSaveChangesFilter.cs b/src/Contrib/Data/Orm/EFCore/Masa.Contrib.Data.EFCore/Filters/SoftDeleteSaveChangesFilter.cs index e7a7f7caf..daecd6275 100644 --- a/src/Contrib/Data/Orm/EFCore/Masa.Contrib.Data.EFCore/Filters/SoftDeleteSaveChangesFilter.cs +++ b/src/Contrib/Data/Orm/EFCore/Masa.Contrib.Data.EFCore/Filters/SoftDeleteSaveChangesFilter.cs @@ -13,16 +13,19 @@ public sealed class SoftDeleteSaveChangesFilter<TDbContext, TUserId> : ISaveChan private readonly IUserContext? _userContext; private readonly TDbContext _context; private readonly MasaDbContextOptions<TDbContext> _masaDbContextOptions; + private readonly ITypeConvertProvider _typeConvertProvider; public SoftDeleteSaveChangesFilter( MasaDbContextOptions<TDbContext> masaDbContextOptions, TDbContext dbContext, - IUserContext? userContext = null) + IUserContext? userContext = null, + ITypeConvertProvider? typeConvertProvider = null) { _userIdType = typeof(TUserId); _masaDbContextOptions = masaDbContextOptions; _context = dbContext; _userContext = userContext; + _typeConvertProvider = typeConvertProvider ?? new DefaultTypeConvertProvider(); } public void OnExecuting(ChangeTracker changeTracker) @@ -103,12 +106,9 @@ private void HandleDependent(object dependentEntry) private object? GetUserId(string? userId) { - if (userId == null) + if (string.IsNullOrWhiteSpace(userId)) return null; - if (_userIdType == typeof(Guid)) - return Guid.Parse(userId); - - return Convert.ChangeType(userId, _userIdType); + return _typeConvertProvider.ConvertTo(userId, _userIdType); } } diff --git a/src/Contrib/Data/Orm/EFCore/Masa.Contrib.Data.EFCore/ITypeAndDefaultValueProvider.cs b/src/Contrib/Data/Orm/EFCore/Masa.Contrib.Data.EFCore/ITypeAndDefaultValueProvider.cs new file mode 100644 index 000000000..8781aec57 --- /dev/null +++ b/src/Contrib/Data/Orm/EFCore/Masa.Contrib.Data.EFCore/ITypeAndDefaultValueProvider.cs @@ -0,0 +1,18 @@ +// Copyright (c) MASA Stack All rights reserved. +// Licensed under the MIT License. See LICENSE.txt in the project root for license information. + +// ReSharper disable once CheckNamespace + +namespace Microsoft.EntityFrameworkCore; + +public interface ITypeAndDefaultValueProvider +{ + /// <summary> + /// Setting type and default value + /// </summary> + /// <param name="type"></param> + /// <returns></returns> + bool TryAdd(Type type); + + bool TryGet(Type type, [NotNullWhen(true)] out string? defaultValue); +} diff --git a/src/Contrib/Data/Orm/EFCore/Masa.Contrib.Data.EFCore/Internal/Extensions/DbContextExtensions.cs b/src/Contrib/Data/Orm/EFCore/Masa.Contrib.Data.EFCore/Internal/Extensions/DbContextExtensions.cs index 79d4b0443..5d09b89d8 100644 --- a/src/Contrib/Data/Orm/EFCore/Masa.Contrib.Data.EFCore/Internal/Extensions/DbContextExtensions.cs +++ b/src/Contrib/Data/Orm/EFCore/Masa.Contrib.Data.EFCore/Internal/Extensions/DbContextExtensions.cs @@ -77,7 +77,10 @@ public static object CreateSaveChangesFilter<TDbContextImplementation>( var userIdType = serviceProvider.GetService<IOptions<AuditEntityOptions>>()?.Value.UserIdType ?? typeof(Guid); return typeof(SaveChangeFilter<,>).MakeGenericType(type, userIdType); }); - return Activator.CreateInstance(saveChangeFilterType, serviceProvider.GetService<IUserContext>())!; + return Activator.CreateInstance(saveChangeFilterType, + serviceProvider.GetService<IUserContext>(), + serviceProvider.GetService<ITypeAndDefaultValueProvider>(), + serviceProvider.GetService<ITypeConvertProvider>())!; } #endregion @@ -99,7 +102,8 @@ public static object CreateSoftDeleteSaveChangesFilter<TDbContextImplementation> softDeleteSaveChangesFilterType, serviceProvider.GetRequiredService<MasaDbContextOptions<TDbContextImplementation>>(), serviceProvider.GetRequiredService<TDbContextImplementation>(), - serviceProvider.GetService<IUserContext>())!; + serviceProvider.GetService<IUserContext>(), + serviceProvider.GetService<ITypeConvertProvider>())!; } #endregion diff --git a/src/Contrib/Data/Orm/EFCore/Masa.Contrib.Data.EFCore/Internal/Isolation/IsolationSaveChangesFilter.cs b/src/Contrib/Data/Orm/EFCore/Masa.Contrib.Data.EFCore/Internal/Isolation/IsolationSaveChangesFilter.cs index 0c5fc0772..faff0f2d2 100644 --- a/src/Contrib/Data/Orm/EFCore/Masa.Contrib.Data.EFCore/Internal/Isolation/IsolationSaveChangesFilter.cs +++ b/src/Contrib/Data/Orm/EFCore/Masa.Contrib.Data.EFCore/Internal/Isolation/IsolationSaveChangesFilter.cs @@ -11,13 +11,13 @@ internal class IsolationSaveChangesFilter<TDbContext, TTenantId> : ISaveChangesF where TTenantId : IComparable { private readonly IMultiTenantContext? _tenantContext; - private readonly IConvertProvider? _convertProvider; + private readonly ITypeConvertProvider _convertProvider; private readonly IMultiEnvironmentContext? _environmentContext; public IsolationSaveChangesFilter(IServiceProvider serviceProvider) { _tenantContext = serviceProvider.GetService<IMultiTenantContext>(); - _convertProvider = serviceProvider.GetService<IConvertProvider>(); + _convertProvider = serviceProvider.GetService<ITypeConvertProvider>() ?? new DefaultTypeConvertProvider(); _environmentContext = serviceProvider.GetService<IMultiEnvironmentContext>(); } @@ -53,10 +53,10 @@ public void OnExecuting(ChangeTracker changeTracker) private object? GetTenantId() { - if (_tenantContext is { CurrentTenant: not null } && !string.IsNullOrEmpty(_tenantContext.CurrentTenant.Id)) + if (_tenantContext is { CurrentTenant: not null } && !string.IsNullOrWhiteSpace(_tenantContext.CurrentTenant.Id)) { ArgumentNullException.ThrowIfNull(_convertProvider, nameof(_convertProvider)); - return _convertProvider.ChangeType(_tenantContext.CurrentTenant.Id, typeof(TTenantId)); + return _convertProvider.ConvertTo(_tenantContext.CurrentTenant.Id, typeof(TTenantId)); } return null; } diff --git a/src/Contrib/Data/Orm/EFCore/Masa.Contrib.Data.EFCore/Internal/TypeExtensions.cs b/src/Contrib/Data/Orm/EFCore/Masa.Contrib.Data.EFCore/Internal/TypeExtensions.cs index 247f25c99..9d87d377b 100644 --- a/src/Contrib/Data/Orm/EFCore/Masa.Contrib.Data.EFCore/Internal/TypeExtensions.cs +++ b/src/Contrib/Data/Orm/EFCore/Masa.Contrib.Data.EFCore/Internal/TypeExtensions.cs @@ -2,6 +2,7 @@ // Licensed under the MIT License. See LICENSE.txt in the project root for license information. [assembly: InternalsVisibleTo("Masa.Contrib.Isolation.EFCore")] + // ReSharper disable once CheckNamespace namespace Masa.Contrib.Data.EFCore; @@ -13,6 +14,4 @@ internal static class TypeExtensions public static bool IsGenericInterfaceAssignableFrom(this Type genericType, Type type) => type.IsConcrete() && type.GetInterfaces().Any(t => t.GetTypeInfo().IsGenericType && t.GetGenericTypeDefinition() == genericType); - - public static readonly MemoryCache<Type, string?> TypeAndDefaultValues = new(); } diff --git a/src/Contrib/Data/Serialization/Masa.Contrib.Data.Serialization.Json/DefaultJsonDeserializer.cs b/src/Contrib/Data/Serialization/Masa.Contrib.Data.Serialization.Json/Internal/DefaultJsonDeserializer.cs similarity index 64% rename from src/Contrib/Data/Serialization/Masa.Contrib.Data.Serialization.Json/DefaultJsonDeserializer.cs rename to src/Contrib/Data/Serialization/Masa.Contrib.Data.Serialization.Json/Internal/DefaultJsonDeserializer.cs index d9bb741b7..7e1975cb4 100644 --- a/src/Contrib/Data/Serialization/Masa.Contrib.Data.Serialization.Json/DefaultJsonDeserializer.cs +++ b/src/Contrib/Data/Serialization/Masa.Contrib.Data.Serialization.Json/Internal/DefaultJsonDeserializer.cs @@ -1,9 +1,15 @@ // Copyright (c) MASA Stack All rights reserved. // Licensed under the MIT License. See LICENSE.txt in the project root for license information. +[assembly: InternalsVisibleTo("Masa.BuildingBlocks.Data.Tests")] +[assembly: InternalsVisibleTo("Masa.Contrib.Data.Serialization.Json.Tests")] +[assembly: InternalsVisibleTo("Masa.Contrib.Extensions.BackgroundJobs.Memory")] + +// ReSharper disable once CheckNamespace + namespace Masa.Contrib.Data.Serialization.Json; -public class DefaultJsonDeserializer : IJsonDeserializer +internal class DefaultJsonDeserializer : IJsonDeserializer { private readonly JsonSerializerOptions? _options; diff --git a/src/Contrib/Data/Serialization/Masa.Contrib.Data.Serialization.Json/DefaultJsonSerializer.cs b/src/Contrib/Data/Serialization/Masa.Contrib.Data.Serialization.Json/Internal/DefaultJsonSerializer.cs similarity index 63% rename from src/Contrib/Data/Serialization/Masa.Contrib.Data.Serialization.Json/DefaultJsonSerializer.cs rename to src/Contrib/Data/Serialization/Masa.Contrib.Data.Serialization.Json/Internal/DefaultJsonSerializer.cs index 802328d99..3cd823c33 100644 --- a/src/Contrib/Data/Serialization/Masa.Contrib.Data.Serialization.Json/DefaultJsonSerializer.cs +++ b/src/Contrib/Data/Serialization/Masa.Contrib.Data.Serialization.Json/Internal/DefaultJsonSerializer.cs @@ -1,9 +1,14 @@ // Copyright (c) MASA Stack All rights reserved. // Licensed under the MIT License. See LICENSE.txt in the project root for license information. +[assembly: InternalsVisibleTo("Masa.Contrib.Data.Serialization.Json.Tests")] +[assembly: InternalsVisibleTo("Masa.Contrib.Extensions.BackgroundJobs.Memory")] + +// ReSharper disable once CheckNamespace + namespace Masa.Contrib.Data.Serialization.Json; -public class DefaultJsonSerializer : IJsonSerializer +internal class DefaultJsonSerializer : IJsonSerializer { private readonly JsonSerializerOptions? _options; diff --git a/src/Contrib/Extensions/Masa.Contrib.Extensions.BackgroundJobs.Memory/Masa.Contrib.Extensions.BackgroundJobs.Memory.csproj b/src/Contrib/Extensions/Masa.Contrib.Extensions.BackgroundJobs.Memory/Masa.Contrib.Extensions.BackgroundJobs.Memory.csproj index 388f9757d..7502d8c50 100644 --- a/src/Contrib/Extensions/Masa.Contrib.Extensions.BackgroundJobs.Memory/Masa.Contrib.Extensions.BackgroundJobs.Memory.csproj +++ b/src/Contrib/Extensions/Masa.Contrib.Extensions.BackgroundJobs.Memory/Masa.Contrib.Extensions.BackgroundJobs.Memory.csproj @@ -14,10 +14,10 @@ <Compile Include="..\..\Data\IdGenerator\NormalGuid\Masa.Contrib.Data.IdGenerator.NormalGuid\NormalGuidGenerator.cs"> <Link>NormalGuidGenerator.cs</Link> </Compile> - <Compile Include="..\..\Data\Serialization\Masa.Contrib.Data.Serialization.Json\DefaultJsonDeserializer.cs"> + <Compile Include="..\..\Data\Serialization\Masa.Contrib.Data.Serialization.Json\Internal\DefaultJsonDeserializer.cs"> <Link>DefaultJsonDeserializer.cs</Link> </Compile> - <Compile Include="..\..\Data\Serialization\Masa.Contrib.Data.Serialization.Json\DefaultJsonSerializer.cs"> + <Compile Include="..\..\Data\Serialization\Masa.Contrib.Data.Serialization.Json\Internal\DefaultJsonSerializer.cs"> <Link>DefaultJsonSerializer.cs</Link> </Compile> </ItemGroup> diff --git a/src/Contrib/Isolation/Masa.Contrib.Isolation.MultiTenant/ConvertProvider.cs b/src/Contrib/Isolation/Masa.Contrib.Isolation.MultiTenant/ConvertProvider.cs deleted file mode 100644 index 38f781c2d..000000000 --- a/src/Contrib/Isolation/Masa.Contrib.Isolation.MultiTenant/ConvertProvider.cs +++ /dev/null @@ -1,13 +0,0 @@ -// Copyright (c) MASA Stack All rights reserved. -// Licensed under the MIT License. See LICENSE.txt in the project root for license information. - -namespace Masa.Contrib.Isolation.MultiTenant; - -public class ConvertProvider : IConvertProvider -{ - public object ChangeType(string value, Type conversionType) - { - var result = conversionType == typeof(Guid) ? Guid.Parse(value) : Convert.ChangeType(value, conversionType); - return result; - } -} diff --git a/src/Contrib/Isolation/Masa.Contrib.Isolation.MultiTenant/IsolationBuilderExtensions.cs b/src/Contrib/Isolation/Masa.Contrib.Isolation.MultiTenant/IsolationBuilderExtensions.cs index 5efbeb110..9aec509ca 100644 --- a/src/Contrib/Isolation/Masa.Contrib.Isolation.MultiTenant/IsolationBuilderExtensions.cs +++ b/src/Contrib/Isolation/Masa.Contrib.Isolation.MultiTenant/IsolationBuilderExtensions.cs @@ -29,7 +29,6 @@ public static IIsolationBuilder UseMultiTenant(this IIsolationBuilder isolationB .AddHttpContextAccessor() .AddTransient(typeof(IEventMiddleware<>), typeof(IsolationEventMiddleware<>)) .AddScoped<IIsolationMiddleware>(serviceProvider => new MultiTenantMiddleware(serviceProvider, tenantName, parserProviders)); - isolationBuilder.Services.TryAddSingleton<IConvertProvider, ConvertProvider>(); isolationBuilder.Services.TryAddScoped<MultiTenantContext>(); isolationBuilder.Services.TryAddScoped(typeof(IMultiTenantContext), serviceProvider => serviceProvider.GetRequiredService<MultiTenantContext>()); isolationBuilder.Services.TryAddScoped(typeof(IMultiTenantSetter), serviceProvider => serviceProvider.GetRequiredService<MultiTenantContext>()); diff --git a/src/Contrib/Isolation/Tests/Masa.Contrib.Isolation.MultiTenant.Tests/TenantTest.cs b/src/Contrib/Isolation/Tests/Masa.Contrib.Isolation.MultiTenant.Tests/TenantTest.cs index cc0e14215..52a36a8b4 100644 --- a/src/Contrib/Isolation/Tests/Masa.Contrib.Isolation.MultiTenant.Tests/TenantTest.cs +++ b/src/Contrib/Isolation/Tests/Masa.Contrib.Isolation.MultiTenant.Tests/TenantTest.cs @@ -21,36 +21,4 @@ public void TestSetTenant() serviceProvider.GetRequiredService<IMultiTenantSetter>().SetTenant(tenant); Assert.IsTrue(serviceProvider.GetRequiredService<IMultiTenantContext>().CurrentTenant == tenant); } - - [TestMethod] - public void TestChangeType() - { - var convertProvider = new ConvertProvider(); - object result = convertProvider.ChangeType("1", typeof(int)); - Assert.IsTrue(result.Equals(1)); - - var guid = Guid.NewGuid(); - result = convertProvider.ChangeType(guid.ToString(), typeof(Guid)); - Assert.IsTrue(result.Equals(guid)); - - var str = "dev"; - result = convertProvider.ChangeType(str, typeof(string)); - Assert.IsTrue(result.Equals(str)); - - result = convertProvider.ChangeType("1.1", typeof(decimal)); - Assert.IsTrue(result.Equals((decimal)1.1)); - - result = convertProvider.ChangeType("1.2", typeof(float)); - Assert.IsTrue(result.Equals((float)1.2)); - - result = convertProvider.ChangeType("1.3", typeof(double)); - Assert.IsTrue(result.Equals(1.3d)); - - result = convertProvider.ChangeType("1", typeof(ushort)); - Assert.IsTrue(result.Equals((ushort)1)); - - bool isProduction = true; - result = convertProvider.ChangeType(isProduction.ToString(), typeof(bool)); - Assert.IsTrue(result.Equals(isProduction)); - } }