diff --git a/framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/Auditing/AbpAuditActionFilter.cs b/framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/Auditing/AbpAuditActionFilter.cs index dfffeea5b4..954a0bd6c7 100644 --- a/framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/Auditing/AbpAuditActionFilter.cs +++ b/framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/Auditing/AbpAuditActionFilter.cs @@ -93,10 +93,11 @@ public class AbpAuditActionFilter : IAsyncActionFilter, ITransientDependency ActionDescriptor actionDescriptor) { if (!abpAuditingOptions.IsEnabledForIntegrationServices && - actionDescriptor - .AsControllerActionDescriptor() - .ControllerTypeInfo - .IsDefined(typeof(IntegrationServiceAttribute), true)) + IntegrationServiceAttribute.IsDefinedOrInherited( + actionDescriptor + .AsControllerActionDescriptor() + .ControllerTypeInfo) + ) { return false; } diff --git a/framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/Conventions/ConventionalControllerSetting.cs b/framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/Conventions/ConventionalControllerSetting.cs index d1b0eef6ab..bb059a6674 100644 --- a/framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/Conventions/ConventionalControllerSetting.cs +++ b/framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/Conventions/ConventionalControllerSetting.cs @@ -4,6 +4,7 @@ using Microsoft.AspNetCore.Mvc.ApplicationModels; using Microsoft.AspNetCore.Mvc.Versioning; using System; using System.Collections.Generic; +using System.Collections.Immutable; using System.Linq; using System.Reflection; using Volo.Abp.Reflection; @@ -16,7 +17,7 @@ public class ConventionalControllerSetting public Assembly Assembly { get; } [NotNull] - public HashSet ControllerTypes { get; } //TODO: Internal? + internal HashSet ControllerTypes { get; } /// /// Set true to use the old style URL path style. @@ -47,6 +48,11 @@ public class ConventionalControllerSetting [CanBeNull] public Func TypePredicate { get; set; } + /// + /// Default value: All. + /// + public ApplicationServiceTypes ApplicationServiceTypes { get; set; } = ApplicationServiceTypes.All; + [CanBeNull] public Action ControllerModelConfigurer { get; set; } @@ -77,6 +83,7 @@ public class ConventionalControllerSetting { var types = Assembly.GetTypes() .Where(IsRemoteService) + .Where(IsPreferredApplicationServiceType) .WhereIf(TypePredicate != null, TypePredicate); foreach (var type in types) @@ -84,6 +91,11 @@ public class ConventionalControllerSetting ControllerTypes.Add(type); } } + + public IReadOnlyList GetControllerTypes() + { + return ControllerTypes.ToImmutableList(); + } private static bool IsRemoteService(Type type) { @@ -105,4 +117,19 @@ public class ConventionalControllerSetting return false; } -} + + private bool IsPreferredApplicationServiceType(Type type) + { + if (ApplicationServiceTypes == ApplicationServiceTypes.ApplicationServices) + { + return !IntegrationServiceAttribute.IsDefinedOrInherited(type); + } + + if (ApplicationServiceTypes == ApplicationServiceTypes.IntegrationServices) + { + return IntegrationServiceAttribute.IsDefinedOrInherited(type); + } + + return true; + } +} \ No newline at end of file diff --git a/framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/Conventions/ConventionalRouteBuilder.cs b/framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/Conventions/ConventionalRouteBuilder.cs index 0906d46006..f9c31467b5 100644 --- a/framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/Conventions/ConventionalRouteBuilder.cs +++ b/framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/Conventions/ConventionalRouteBuilder.cs @@ -73,7 +73,7 @@ public class ConventionalRouteBuilder : IConventionalRouteBuilder, ITransientDep protected virtual string GetApiRoutePrefix(ActionModel actionModel, ConventionalControllerSetting configuration) { - if (actionModel.Controller.ControllerType.IsDefined(typeof(IntegrationServiceAttribute), true)) + if (IntegrationServiceAttribute.IsDefinedOrInherited(actionModel.Controller.ControllerType)) { return AbpAspNetCoreConsts.DefaultIntegrationServiceApiPrefix; } diff --git a/framework/src/Volo.Abp.Auditing/Volo/Abp/Auditing/AuditingInterceptorRegistrar.cs b/framework/src/Volo.Abp.Auditing/Volo/Abp/Auditing/AuditingInterceptorRegistrar.cs index db5d44cec5..ca07c75516 100644 --- a/framework/src/Volo.Abp.Auditing/Volo/Abp/Auditing/AuditingInterceptorRegistrar.cs +++ b/framework/src/Volo.Abp.Auditing/Volo/Abp/Auditing/AuditingInterceptorRegistrar.cs @@ -52,7 +52,8 @@ public static class AuditingInterceptorRegistrar if (typeof(IAuditingEnabled).IsAssignableFrom(type)) { - if (ignoreIntegrationServiceAttribute || !type.IsDefined(typeof(IntegrationServiceAttribute), true)) + if (ignoreIntegrationServiceAttribute || + !IntegrationServiceAttribute.IsDefinedOrInherited(type)) { return true; } diff --git a/framework/src/Volo.Abp.Core/Volo/Abp/ApplicationServiceTypes.cs b/framework/src/Volo.Abp.Core/Volo/Abp/ApplicationServiceTypes.cs new file mode 100644 index 0000000000..47eeb99d47 --- /dev/null +++ b/framework/src/Volo.Abp.Core/Volo/Abp/ApplicationServiceTypes.cs @@ -0,0 +1,22 @@ +using System; + +namespace Volo.Abp; + +[Flags] +public enum ApplicationServiceTypes : byte +{ + /// + /// Only application services without . + /// + ApplicationServices = 1, + + /// + /// Application services with . + /// + IntegrationServices = 2, + + /// + /// All application services. + /// + All = ApplicationServices | IntegrationServices +} \ No newline at end of file diff --git a/framework/src/Volo.Abp.Core/Volo/Abp/IntegrationServiceAttribute.cs b/framework/src/Volo.Abp.Core/Volo/Abp/IntegrationServiceAttribute.cs index 016a7a49c7..22ab4ca9e9 100644 --- a/framework/src/Volo.Abp.Core/Volo/Abp/IntegrationServiceAttribute.cs +++ b/framework/src/Volo.Abp.Core/Volo/Abp/IntegrationServiceAttribute.cs @@ -2,8 +2,29 @@ namespace Volo.Abp; -[AttributeUsage(AttributeTargets.Class)] +[AttributeUsage(AttributeTargets.Class | AttributeTargets.Interface)] public class IntegrationServiceAttribute : Attribute { - + public static bool IsDefinedOrInherited() + { + return IsDefinedOrInherited(typeof(T)); + } + + public static bool IsDefinedOrInherited(Type type) + { + if (type.IsDefined(typeof(IntegrationServiceAttribute), true)) + { + return true; + } + + foreach (var @interface in type.GetInterfaces()) + { + if (@interface.IsDefined(typeof(IntegrationServiceAttribute), true)) + { + return true; + } + } + + return false; + } } \ No newline at end of file diff --git a/framework/src/Volo.Abp.Http.Client/Microsoft/Extensions/DependencyInjection/ServiceCollectionHttpClientProxyExtensions.cs b/framework/src/Volo.Abp.Http.Client/Microsoft/Extensions/DependencyInjection/ServiceCollectionHttpClientProxyExtensions.cs index 57233ac972..2f7942fabe 100644 --- a/framework/src/Volo.Abp.Http.Client/Microsoft/Extensions/DependencyInjection/ServiceCollectionHttpClientProxyExtensions.cs +++ b/framework/src/Volo.Abp.Http.Client/Microsoft/Extensions/DependencyInjection/ServiceCollectionHttpClientProxyExtensions.cs @@ -28,14 +28,22 @@ public static class ServiceCollectionHttpClientProxyExtensions /// The name of the remote service configuration to be used by the Static HTTP Client proxies. /// See . /// + /// + /// Can be set to filter the application service types to be registered. + /// Default value: All. + /// public static IServiceCollection AddStaticHttpClientProxies( [NotNull] this IServiceCollection services, [NotNull] Assembly assembly, - [NotNull] string remoteServiceConfigurationName = RemoteServiceConfigurationDictionary.DefaultName) + [NotNull] string remoteServiceConfigurationName = RemoteServiceConfigurationDictionary.DefaultName, + ApplicationServiceTypes applicationServiceTypes = ApplicationServiceTypes.All) { Check.NotNull(services, nameof(assembly)); - var serviceTypes = assembly.GetTypes().Where(IsSuitableForClientProxying).ToArray(); + var serviceTypes = assembly + .GetTypes() + .Where(x => IsSuitableForClientProxying(x, applicationServiceTypes)) + .ToArray(); foreach (var serviceType in serviceTypes) { @@ -64,15 +72,23 @@ public static class ServiceCollectionHttpClientProxyExtensions /// /// True, to register the HTTP client proxy as the default implementation for the services. /// + /// + /// Can be set to filter the application service types to be registered. + /// Default value: All. + /// public static IServiceCollection AddHttpClientProxies( [NotNull] this IServiceCollection services, [NotNull] Assembly assembly, [NotNull] string remoteServiceConfigurationName = RemoteServiceConfigurationDictionary.DefaultName, - bool asDefaultServices = true) + bool asDefaultServices = true, + ApplicationServiceTypes applicationServiceTypes = ApplicationServiceTypes.All) { Check.NotNull(services, nameof(assembly)); - var serviceTypes = assembly.GetTypes().Where(IsSuitableForClientProxying).ToArray(); + var serviceTypes = assembly + .GetTypes() + .Where(x => IsSuitableForClientProxying(x, applicationServiceTypes)) + .ToArray(); foreach (var serviceType in serviceTypes) { @@ -228,13 +244,28 @@ public static class ServiceCollectionHttpClientProxyExtensions /// /// Type to check /// True, if the type is suitable for proxying. Otherwise false. - private static bool IsSuitableForClientProxying(Type type) + private static bool IsSuitableForClientProxying( + Type type, + ApplicationServiceTypes applicationServiceTypes) { - //TODO: Add option to change type filter + if (!type.IsInterface || + !type.IsPublic || + type.IsGenericType || + !typeof(IRemoteService).IsAssignableFrom(type)) + { + return false; + } + + if (applicationServiceTypes == ApplicationServiceTypes.ApplicationServices) + { + return !IntegrationServiceAttribute.IsDefinedOrInherited(type); + } + + if (applicationServiceTypes == ApplicationServiceTypes.IntegrationServices) + { + return IntegrationServiceAttribute.IsDefinedOrInherited(type); + } - return type.IsInterface - && type.IsPublic - && !type.IsGenericType - && typeof(IRemoteService).IsAssignableFrom(type); + return true; } } diff --git a/framework/test/Volo.Abp.Core.Tests/Volo/Abp/IntegrationServiceAttribute_Tests.cs b/framework/test/Volo.Abp.Core.Tests/Volo/Abp/IntegrationServiceAttribute_Tests.cs new file mode 100644 index 0000000000..aa2d9d578a --- /dev/null +++ b/framework/test/Volo.Abp.Core.Tests/Volo/Abp/IntegrationServiceAttribute_Tests.cs @@ -0,0 +1,48 @@ +using Shouldly; +using Xunit; + +namespace Volo.Abp; + +public class IntegrationServiceAttribute_Tests +{ + [Fact] + public static void IsDefinedOrInherited() + { + // True cases + + IntegrationServiceAttribute + .IsDefinedOrInherited() + .ShouldBeTrue(); + + IntegrationServiceAttribute + .IsDefinedOrInherited() + .ShouldBeTrue(); + + IntegrationServiceAttribute + .IsDefinedOrInherited() + .ShouldBeTrue(); + + // False cases + + IntegrationServiceAttribute + .IsDefinedOrInherited() + .ShouldBeFalse(); + + IntegrationServiceAttribute + .IsDefinedOrInherited() + .ShouldBeFalse(); + + } + + [IntegrationService] + private interface IMyIntegrationService1 { } + private class MyIntegrationService1 : IMyIntegrationService1 { } + + private interface IMyIntegrationService2 { } + [IntegrationService] + private class MyIntegrationService2 : IMyIntegrationService2 { } + + private interface IMyApplicationService { } + private class MyApplicationService : IMyApplicationService { } +} +