From d7cf09578921e45001b14c285b985cc9a586894c Mon Sep 17 00:00:00 2001 From: maliming Date: Mon, 21 Aug 2023 10:35:59 +0800 Subject: [PATCH] Add `IsReadOnly` to `IRepository`. --- .../ServiceCollectionRepositoryExtensions.cs | 29 +++++++++---- .../Repositories/BasicRepositoryBase.cs | 3 ++ .../Abp/Domain/Repositories/IRepository.cs | 2 +- .../ServiceCollectionShouldlyExtensions.cs | 11 +++++ .../RepositoryRegistration_Tests.cs | 42 +++++++++---------- 5 files changed, 58 insertions(+), 29 deletions(-) diff --git a/framework/src/Volo.Abp.Ddd.Domain/Microsoft/Extensions/DependencyInjection/ServiceCollectionRepositoryExtensions.cs b/framework/src/Volo.Abp.Ddd.Domain/Microsoft/Extensions/DependencyInjection/ServiceCollectionRepositoryExtensions.cs index c63a5442c7..f1e5068bc6 100644 --- a/framework/src/Volo.Abp.Ddd.Domain/Microsoft/Extensions/DependencyInjection/ServiceCollectionRepositoryExtensions.cs +++ b/framework/src/Volo.Abp.Ddd.Domain/Microsoft/Extensions/DependencyInjection/ServiceCollectionRepositoryExtensions.cs @@ -1,5 +1,6 @@ using System; using Microsoft.Extensions.DependencyInjection.Extensions; +using Volo.Abp; using Volo.Abp.Domain.Entities; using Volo.Abp.Domain.Repositories; @@ -17,13 +18,13 @@ public static class ServiceCollectionRepositoryExtensions var readOnlyBasicRepositoryInterface = typeof(IReadOnlyBasicRepository<>).MakeGenericType(entityType); if (readOnlyBasicRepositoryInterface.IsAssignableFrom(repositoryImplementationType)) { - RegisterService(services, readOnlyBasicRepositoryInterface, repositoryImplementationType, replaceExisting); + RegisterService(services, readOnlyBasicRepositoryInterface, repositoryImplementationType, replaceExisting, true); //IReadOnlyRepository var readOnlyRepositoryInterface = typeof(IReadOnlyRepository<>).MakeGenericType(entityType); if (readOnlyRepositoryInterface.IsAssignableFrom(repositoryImplementationType)) { - RegisterService(services, readOnlyRepositoryInterface, repositoryImplementationType, replaceExisting); + RegisterService(services, readOnlyRepositoryInterface, repositoryImplementationType, replaceExisting, true); } //IBasicRepository @@ -48,13 +49,13 @@ public static class ServiceCollectionRepositoryExtensions var readOnlyBasicRepositoryInterfaceWithPk = typeof(IReadOnlyBasicRepository<,>).MakeGenericType(entityType, primaryKeyType); if (readOnlyBasicRepositoryInterfaceWithPk.IsAssignableFrom(repositoryImplementationType)) { - RegisterService(services, readOnlyBasicRepositoryInterfaceWithPk, repositoryImplementationType, replaceExisting); + RegisterService(services, readOnlyBasicRepositoryInterfaceWithPk, repositoryImplementationType, replaceExisting, true); //IReadOnlyRepository var readOnlyRepositoryInterfaceWithPk = typeof(IReadOnlyRepository<,>).MakeGenericType(entityType, primaryKeyType); if (readOnlyRepositoryInterfaceWithPk.IsAssignableFrom(repositoryImplementationType)) { - RegisterService(services, readOnlyRepositoryInterfaceWithPk, repositoryImplementationType, replaceExisting); + RegisterService(services, readOnlyRepositoryInterfaceWithPk, repositoryImplementationType, replaceExisting, true); } //IBasicRepository @@ -80,15 +81,29 @@ public static class ServiceCollectionRepositoryExtensions IServiceCollection services, Type serviceType, Type implementationType, - bool replaceExisting) + bool replaceExisting, + bool isReadOnly = false) { + var descriptor = ServiceDescriptor.Transient(serviceType, implementationType); + + if (isReadOnly) + { + services.AddTransient(implementationType); + descriptor = ServiceDescriptor.Transient(serviceType, provider => + { + var repository = provider.GetRequiredService(implementationType); + ObjectHelper.TrySetProperty(repository.As(), x => x.IsReadOnly, _ => true); + return repository; + }); + } + if (replaceExisting) { - services.Replace(ServiceDescriptor.Transient(serviceType, implementationType)); + services.Replace(descriptor); } else { - services.TryAddTransient(serviceType, implementationType); + services.TryAdd(descriptor); } } } diff --git a/framework/src/Volo.Abp.Ddd.Domain/Volo/Abp/Domain/Repositories/BasicRepositoryBase.cs b/framework/src/Volo.Abp.Ddd.Domain/Volo/Abp/Domain/Repositories/BasicRepositoryBase.cs index 0d86045eea..44d10b36ae 100644 --- a/framework/src/Volo.Abp.Ddd.Domain/Volo/Abp/Domain/Repositories/BasicRepositoryBase.cs +++ b/framework/src/Volo.Abp.Ddd.Domain/Volo/Abp/Domain/Repositories/BasicRepositoryBase.cs @@ -34,6 +34,9 @@ public abstract class BasicRepositoryBase : public ICancellationTokenProvider CancellationTokenProvider => LazyServiceProvider.LazyGetService(NullCancellationTokenProvider.Instance); + + public bool IsReadOnly { get; set; } = false; + protected BasicRepositoryBase() { diff --git a/framework/src/Volo.Abp.Ddd.Domain/Volo/Abp/Domain/Repositories/IRepository.cs b/framework/src/Volo.Abp.Ddd.Domain/Volo/Abp/Domain/Repositories/IRepository.cs index 3c7ae81875..d50a881c28 100644 --- a/framework/src/Volo.Abp.Ddd.Domain/Volo/Abp/Domain/Repositories/IRepository.cs +++ b/framework/src/Volo.Abp.Ddd.Domain/Volo/Abp/Domain/Repositories/IRepository.cs @@ -12,7 +12,7 @@ namespace Volo.Abp.Domain.Repositories; /// public interface IRepository { - + bool IsReadOnly { get; } } public interface IRepository : IReadOnlyRepository, IBasicRepository diff --git a/framework/test/AbpTestBase/Microsoft/Extensions/DependencyInjection/ServiceCollectionShouldlyExtensions.cs b/framework/test/AbpTestBase/Microsoft/Extensions/DependencyInjection/ServiceCollectionShouldlyExtensions.cs index 6c3f8e5090..541b62f58d 100644 --- a/framework/test/AbpTestBase/Microsoft/Extensions/DependencyInjection/ServiceCollectionShouldlyExtensions.cs +++ b/framework/test/AbpTestBase/Microsoft/Extensions/DependencyInjection/ServiceCollectionShouldlyExtensions.cs @@ -17,6 +17,17 @@ public static class ServiceCollectionShouldlyExtensions serviceDescriptor.Lifetime.ShouldBe(ServiceLifetime.Transient); } + public static void ShouldContainTransientImplementationFactory(this IServiceCollection services, Type serviceType) + { + var serviceDescriptor = services.FirstOrDefault(s => s.ServiceType == serviceType); + + serviceDescriptor.ShouldNotBeNull(); + serviceDescriptor.ImplementationType.ShouldBeNull(); + serviceDescriptor.ImplementationFactory.ShouldNotBeNull(); + serviceDescriptor.ImplementationInstance.ShouldBeNull(); + serviceDescriptor.Lifetime.ShouldBe(ServiceLifetime.Transient); + } + public static void ShouldContainSingleton(this IServiceCollection services, Type serviceType, Type implementationType = null) { var serviceDescriptor = services.FirstOrDefault(s => s.ServiceType == serviceType); diff --git a/framework/test/Volo.Abp.Ddd.Tests/Volo/Abp/Domain/Repositories/RepositoryRegistration_Tests.cs b/framework/test/Volo.Abp.Ddd.Tests/Volo/Abp/Domain/Repositories/RepositoryRegistration_Tests.cs index e6e17b253c..c12909bc98 100644 --- a/framework/test/Volo.Abp.Ddd.Tests/Volo/Abp/Domain/Repositories/RepositoryRegistration_Tests.cs +++ b/framework/test/Volo.Abp.Ddd.Tests/Volo/Abp/Domain/Repositories/RepositoryRegistration_Tests.cs @@ -31,15 +31,15 @@ public class RepositoryRegistration_Tests //Assert //MyTestAggregateRootWithoutPk - services.ShouldContainTransient(typeof(IReadOnlyRepository), typeof(MyTestDefaultRepository)); + services.ShouldContainTransientImplementationFactory(typeof(IReadOnlyRepository)); services.ShouldContainTransient(typeof(IBasicRepository), typeof(MyTestDefaultRepository)); services.ShouldContainTransient(typeof(IRepository), typeof(MyTestDefaultRepository)); //MyTestAggregateRootWithGuidPk - services.ShouldContainTransient(typeof(IReadOnlyRepository), typeof(MyTestDefaultRepository)); + services.ShouldContainTransientImplementationFactory(typeof(IReadOnlyRepository)); services.ShouldContainTransient(typeof(IBasicRepository), typeof(MyTestDefaultRepository)); services.ShouldContainTransient(typeof(IRepository), typeof(MyTestDefaultRepository)); - services.ShouldContainTransient(typeof(IReadOnlyRepository), typeof(MyTestDefaultRepository)); + services.ShouldContainTransientImplementationFactory(typeof(IReadOnlyRepository)); services.ShouldContainTransient(typeof(IBasicRepository), typeof(MyTestDefaultRepository)); services.ShouldContainTransient(typeof(IRepository), typeof(MyTestDefaultRepository)); @@ -69,24 +69,24 @@ public class RepositoryRegistration_Tests //Assert //MyTestAggregateRootWithoutPk - services.ShouldContainTransient(typeof(IReadOnlyRepository), typeof(MyTestDefaultRepository)); + services.ShouldContainTransientImplementationFactory(typeof(IReadOnlyRepository)); services.ShouldContainTransient(typeof(IBasicRepository), typeof(MyTestDefaultRepository)); services.ShouldContainTransient(typeof(IRepository), typeof(MyTestDefaultRepository)); //MyTestAggregateRootWithGuidPk - services.ShouldContainTransient(typeof(IReadOnlyRepository), typeof(MyTestDefaultRepository)); + services.ShouldContainTransientImplementationFactory(typeof(IReadOnlyRepository)); services.ShouldContainTransient(typeof(IBasicRepository), typeof(MyTestDefaultRepository)); services.ShouldContainTransient(typeof(IRepository), typeof(MyTestDefaultRepository)); - services.ShouldContainTransient(typeof(IReadOnlyRepository), typeof(MyTestDefaultRepository)); + services.ShouldContainTransientImplementationFactory(typeof(IReadOnlyRepository)); services.ShouldContainTransient(typeof(IBasicRepository), typeof(MyTestDefaultRepository)); services.ShouldContainTransient(typeof(IRepository), typeof(MyTestDefaultRepository)); //MyTestEntityWithInt32Pk - services.ShouldContainTransient(typeof(IReadOnlyRepository), typeof(MyTestDefaultRepository)); + services.ShouldContainTransientImplementationFactory(typeof(IReadOnlyRepository)); services.ShouldContainTransient(typeof(IBasicRepository), typeof(MyTestDefaultRepository)); services.ShouldContainTransient(typeof(IRepository), typeof(MyTestDefaultRepository)); - services.ShouldContainTransient(typeof(IReadOnlyRepository), typeof(MyTestDefaultRepository)); - services.ShouldContainTransient(typeof(IReadOnlyBasicRepository), typeof(MyTestDefaultRepository)); + services.ShouldContainTransientImplementationFactory(typeof(IReadOnlyRepository)); + services.ShouldContainTransientImplementationFactory(typeof(IReadOnlyBasicRepository)); services.ShouldContainTransient(typeof(IBasicRepository), typeof(MyTestDefaultRepository)); services.ShouldContainTransient(typeof(IRepository), typeof(MyTestDefaultRepository)); } @@ -114,20 +114,20 @@ public class RepositoryRegistration_Tests services.ShouldContainTransient(typeof(IRepository), typeof(MyTestDefaultRepository)); //MyTestAggregateRootWithGuidPk - services.ShouldContainTransient(typeof(IReadOnlyRepository), typeof(MyTestAggregateRootWithDefaultPkCustomRepository)); + services.ShouldContainTransientImplementationFactory(typeof(IReadOnlyRepository)); services.ShouldContainTransient(typeof(IBasicRepository), typeof(MyTestAggregateRootWithDefaultPkCustomRepository)); services.ShouldContainTransient(typeof(IRepository), typeof(MyTestAggregateRootWithDefaultPkCustomRepository)); - services.ShouldContainTransient(typeof(IReadOnlyRepository), typeof(MyTestAggregateRootWithDefaultPkCustomRepository)); - services.ShouldContainTransient(typeof(IReadOnlyBasicRepository), typeof(MyTestAggregateRootWithDefaultPkCustomRepository)); + services.ShouldContainTransientImplementationFactory(typeof(IReadOnlyRepository)); + services.ShouldContainTransientImplementationFactory(typeof(IReadOnlyBasicRepository)); services.ShouldContainTransient(typeof(IBasicRepository), typeof(MyTestAggregateRootWithDefaultPkCustomRepository)); services.ShouldContainTransient(typeof(IRepository), typeof(MyTestAggregateRootWithDefaultPkCustomRepository)); //MyTestEntityWithInt32Pk - services.ShouldContainTransient(typeof(IReadOnlyRepository), typeof(MyTestDefaultRepository)); + services.ShouldContainTransientImplementationFactory(typeof(IReadOnlyRepository)); services.ShouldContainTransient(typeof(IBasicRepository), typeof(MyTestDefaultRepository)); services.ShouldContainTransient(typeof(IRepository), typeof(MyTestDefaultRepository)); - services.ShouldContainTransient(typeof(IReadOnlyRepository), typeof(MyTestDefaultRepository)); - services.ShouldContainTransient(typeof(IReadOnlyBasicRepository), typeof(MyTestDefaultRepository)); + services.ShouldContainTransientImplementationFactory(typeof(IReadOnlyRepository)); + services.ShouldContainTransientImplementationFactory(typeof(IReadOnlyBasicRepository)); services.ShouldContainTransient(typeof(IBasicRepository), typeof(MyTestDefaultRepository)); services.ShouldContainTransient(typeof(IRepository), typeof(MyTestDefaultRepository)); } @@ -209,10 +209,10 @@ public class RepositoryRegistration_Tests services.ShouldNotContainService(typeof(IRepository)); //MyTestAggregateRootWithGuidPk - services.ShouldContainTransient(typeof(IReadOnlyRepository), typeof(MyTestDefaultRepository)); + services.ShouldContainTransientImplementationFactory(typeof(IReadOnlyRepository)); services.ShouldContainTransient(typeof(IBasicRepository), typeof(MyTestDefaultRepository)); services.ShouldContainTransient(typeof(IRepository), typeof(MyTestDefaultRepository)); - services.ShouldContainTransient(typeof(IReadOnlyRepository), typeof(MyTestDefaultRepository)); + services.ShouldContainTransientImplementationFactory(typeof(IReadOnlyRepository)); services.ShouldContainTransient(typeof(IBasicRepository), typeof(MyTestDefaultRepository)); services.ShouldContainTransient(typeof(IRepository), typeof(MyTestDefaultRepository)); } @@ -234,11 +234,11 @@ public class RepositoryRegistration_Tests new MyTestRepositoryRegistrar(options).AddRepositories(); //MyTestAggregateRootWithGuidPk - services.ShouldContainTransient(typeof(IReadOnlyRepository), typeof(MyTestAggregateRootWithDefaultPkCustomRepository)); + services.ShouldContainTransientImplementationFactory(typeof(IReadOnlyRepository)); services.ShouldContainTransient(typeof(IBasicRepository), typeof(MyTestAggregateRootWithDefaultPkCustomRepository)); services.ShouldContainTransient(typeof(IRepository), typeof(MyTestAggregateRootWithDefaultPkCustomRepository)); - services.ShouldContainTransient(typeof(IReadOnlyRepository), typeof(MyTestAggregateRootWithDefaultPkCustomRepository)); - services.ShouldContainTransient(typeof(IReadOnlyBasicRepository), typeof(MyTestAggregateRootWithDefaultPkCustomRepository)); + services.ShouldContainTransientImplementationFactory(typeof(IReadOnlyRepository)); + services.ShouldContainTransientImplementationFactory(typeof(IReadOnlyBasicRepository)); services.ShouldContainTransient(typeof(IBasicRepository), typeof(MyTestAggregateRootWithDefaultPkCustomRepository)); services.ShouldContainTransient(typeof(IRepository), typeof(MyTestAggregateRootWithDefaultPkCustomRepository)); } @@ -407,7 +407,7 @@ public class RepositoryRegistration_Tests public class MyTestAggregateRootWithDefaultPkEmptyRepository : IMyTestAggregateRootWithDefaultPkEmptyRepository { - + public bool IsReadOnly { get; set; } = false; } public class TestDbContextRegistrationOptions : AbpCommonDbContextRegistrationOptions