diff --git a/src/Volo.Abp.Autofac/Autofac/Builder/AbpRegistrationBuilderExtensions.cs b/src/Volo.Abp.Autofac/Autofac/Builder/AbpRegistrationBuilderExtensions.cs index e26f6b4070..be674e82dd 100644 --- a/src/Volo.Abp.Autofac/Autofac/Builder/AbpRegistrationBuilderExtensions.cs +++ b/src/Volo.Abp.Autofac/Autofac/Builder/AbpRegistrationBuilderExtensions.cs @@ -38,8 +38,7 @@ namespace Autofac.Builder private static IRegistrationBuilder AddInterceptors( this IRegistrationBuilder registrationBuilder, - Type[] interceptors - ) + Type[] interceptors) where TConcreteReflectionActivatorData : ConcreteReflectionActivatorData { var serviceType = registrationBuilder.RegistrationData.Services.OfType().FirstOrDefault()?.ServiceType; diff --git a/src/Volo.Abp/Microsoft/Extensions/DependencyInjection/OnServiceRegistredArgs.cs b/src/Volo.Abp/Microsoft/Extensions/DependencyInjection/OnServiceRegistredArgs.cs index eb241be871..39217bb83c 100644 --- a/src/Volo.Abp/Microsoft/Extensions/DependencyInjection/OnServiceRegistredArgs.cs +++ b/src/Volo.Abp/Microsoft/Extensions/DependencyInjection/OnServiceRegistredArgs.cs @@ -1,4 +1,5 @@ using System; +using JetBrains.Annotations; using Volo; using Volo.Abp.Collections; using Volo.Abp.DynamicProxy; @@ -11,7 +12,7 @@ namespace Microsoft.Extensions.DependencyInjection public virtual Type ImplementationType { get; } - public OnServiceRegistredArgs(Type implementationType) + public OnServiceRegistredArgs([NotNull] Type implementationType) { ImplementationType = Check.NotNull(implementationType, nameof(implementationType)); diff --git a/src/Volo.Abp/Microsoft/Extensions/DependencyInjection/ServiceCollectionRegistrationActionExtensions.cs b/src/Volo.Abp/Microsoft/Extensions/DependencyInjection/ServiceCollectionRegistrationActionExtensions.cs index 63e8764ee4..ace3558005 100644 --- a/src/Volo.Abp/Microsoft/Extensions/DependencyInjection/ServiceCollectionRegistrationActionExtensions.cs +++ b/src/Volo.Abp/Microsoft/Extensions/DependencyInjection/ServiceCollectionRegistrationActionExtensions.cs @@ -17,14 +17,36 @@ namespace Microsoft.Extensions.DependencyInjection private static ServiceRegistrationActionList GetOrCreateServiceActionList(IServiceCollection services) { - var registrationActionList = services.GetSingletonInstanceOrNull>()?.Value; - if (registrationActionList == null) + var actionList = services.GetSingletonInstanceOrNull>()?.Value; + if (actionList == null) { - registrationActionList = new ServiceRegistrationActionList(); - services.AddObjectAccessor(registrationActionList); + actionList = new ServiceRegistrationActionList(); + services.AddObjectAccessor(actionList); } - return registrationActionList; + return actionList; + } + + public static void OnServiceExposing(this IServiceCollection services, Action exposeAction) + { + GetOrCreateOnServiceExposingList(services).Add(exposeAction); + } + + public static ServiceExposingActionList GetServiceExposingActionList(this IServiceCollection services) + { + return GetOrCreateOnServiceExposingList(services); + } + + private static ServiceExposingActionList GetOrCreateOnServiceExposingList(IServiceCollection services) + { + var actionList = services.GetSingletonInstanceOrNull>()?.Value; + if (actionList == null) + { + actionList = new ServiceExposingActionList(); + services.AddObjectAccessor(actionList); + } + + return actionList; } } } diff --git a/src/Volo.Abp/Volo/Abp/AbpKernelModule.cs b/src/Volo.Abp/Volo/Abp/AbpKernelModule.cs index 549f9ccf5d..b28e07ec87 100644 --- a/src/Volo.Abp/Volo/Abp/AbpKernelModule.cs +++ b/src/Volo.Abp/Volo/Abp/AbpKernelModule.cs @@ -3,6 +3,8 @@ using System.Reflection; using Microsoft.Extensions.DependencyInjection; using Volo.Abp.Application.Services; using Volo.Abp.Modularity; +using Volo.Abp.ObjectMapping; +using Volo.Abp.Reflection; using Volo.Abp.Uow; using Volo.DependencyInjection; @@ -12,7 +14,25 @@ namespace Volo.Abp { public override void PreConfigureServices(IServiceCollection services) { - services.OnServiceRegistred(registration => { RegisterUnitOfWorkInterceptor(registration); }); + //TODO: Move these to dedicated class(es) + + services.OnServiceRegistred(registration => + { + if (typeof(IApplicationService).GetTypeInfo().IsAssignableFrom(registration.ImplementationType)) + { + registration.Interceptors.Add(); + } + }); + + services.OnServiceExposing(context => + { + context.ExposedTypes.AddRange( + ReflectionHelper.GetImplementedGenericTypes( + context.ImplementationType, + typeof(IObjectMapper<,>) + ) + ); + }); } public override void ConfigureServices(IServiceCollection services) @@ -29,13 +49,5 @@ namespace Volo.Abp { context.ServiceProvider.GetRequiredService>().Value = context.ServiceProvider; } - - private static void RegisterUnitOfWorkInterceptor(IOnServiceRegistredArgs registration) - { - if (typeof(IApplicationService).GetTypeInfo().IsAssignableFrom(registration.ImplementationType)) - { - registration.Interceptors.Add(); - } - } } } diff --git a/src/Volo.Abp/Volo/Abp/ObjectMapping/IObjectMapper.cs b/src/Volo.Abp/Volo/Abp/ObjectMapping/IObjectMapper.cs index cc28d69ca0..88ee14d707 100644 --- a/src/Volo.Abp/Volo/Abp/ObjectMapping/IObjectMapper.cs +++ b/src/Volo.Abp/Volo/Abp/ObjectMapping/IObjectMapper.cs @@ -1,7 +1,7 @@ namespace Volo.Abp.ObjectMapping { /// - /// Defines a simple interface to map objects. + /// Defines a simple interface to automatically map objects. /// public interface IObjectMapper { @@ -24,10 +24,26 @@ TDestination Map(TSource source, TDestination destination); } + /// + /// Maps an object to another. + /// Implement this interface to override object to object mapping for specific types. + /// + /// + /// public interface IObjectMapper { + /// + /// Converts an object to another. Creates a new object of . + /// + /// Source object TDestination Map(TSource source); + /// + /// Execute a mapping from the source object to the existing destination object + /// + /// Source object + /// Destination object + /// Returns the same object after mapping operation TDestination Map(TSource source, TDestination destination); } } diff --git a/src/Volo.Abp/Volo/Abp/Reflection/ReflectionHelper.cs b/src/Volo.Abp/Volo/Abp/Reflection/ReflectionHelper.cs index c8c47a3534..7175f6fe7c 100644 --- a/src/Volo.Abp/Volo/Abp/Reflection/ReflectionHelper.cs +++ b/src/Volo.Abp/Volo/Abp/Reflection/ReflectionHelper.cs @@ -1,10 +1,13 @@ using System; +using System.Collections.Generic; using System.Reflection; namespace Volo.Abp.Reflection { + //TODO: Consider to make internal public static class ReflectionHelper { + //TODO: Ehhance summary /// /// Checks whether implements/inherits . /// @@ -34,5 +37,38 @@ namespace Volo.Abp.Reflection return IsAssignableToGenericType(givenTypeInfo.BaseType, genericType); } + + //TODO: Summary + public static List GetImplementedGenericTypes(Type givenType, Type genericType) + { + var result = new List(); + AddImplementedGenericTypes(result, givenType, genericType); + return result; + } + + private static void AddImplementedGenericTypes(List result, Type givenType, Type genericType) + { + var givenTypeInfo = givenType.GetTypeInfo(); + + if (givenTypeInfo.IsGenericType && givenType.GetGenericTypeDefinition() == genericType) + { + result.Add(givenType); + } + + foreach (var interfaceType in givenTypeInfo.GetInterfaces()) + { + if (interfaceType.GetTypeInfo().IsGenericType && interfaceType.GetGenericTypeDefinition() == genericType) + { + result.Add(interfaceType); + } + } + + if (givenTypeInfo.BaseType == null) + { + return; + } + + AddImplementedGenericTypes(result, givenTypeInfo.BaseType, genericType); + } } } diff --git a/src/Volo.Abp/Volo/DependencyInjection/AutoRegistrationHelper.cs b/src/Volo.Abp/Volo/DependencyInjection/AutoRegistrationHelper.cs index ed279475fd..f3762c8147 100644 --- a/src/Volo.Abp/Volo/DependencyInjection/AutoRegistrationHelper.cs +++ b/src/Volo.Abp/Volo/DependencyInjection/AutoRegistrationHelper.cs @@ -2,20 +2,21 @@ using System.Collections.Generic; using System.Linq; using System.Reflection; +using Microsoft.Extensions.DependencyInjection; using Volo.ExtensionMethods; namespace Volo.DependencyInjection { public static class AutoRegistrationHelper { - public static IEnumerable GetExposedServices(Type type) + public static IEnumerable GetExposedServices(IServiceCollection services, Type type) { var typeInfo = type.GetTypeInfo(); var customExposedServices = typeInfo .GetCustomAttributes() .OfType() - .SelectMany(p => p.GetExposedServiceTypes()) + .SelectMany(p => p.GetExposedServiceTypes(type)) .ToList(); if (customExposedServices.Any()) @@ -23,17 +24,14 @@ namespace Volo.DependencyInjection return customExposedServices; } - return GetDefaultExposedServices(type); + return GetDefaultExposedServices(services, type); } - public static IEnumerable GetDefaultExposedServices(Type type, bool includeSelf = true) + private static IEnumerable GetDefaultExposedServices(IServiceCollection services, Type type) { var serviceTypes = new List(); - if (includeSelf) - { - serviceTypes.Add(type); - } + serviceTypes.Add(type); foreach (var interfaceType in type.GetTypeInfo().GetInterfaces()) { @@ -50,6 +48,16 @@ namespace Volo.DependencyInjection } } + var exposeActions = services.GetServiceExposingActionList(); + if (exposeActions.Any()) + { + var args = new OnServiceExposingArgs(type, serviceTypes); + foreach (var action in services.GetServiceExposingActionList()) + { + action(args); + } + } + return serviceTypes; } } diff --git a/src/Volo.Abp/Volo/DependencyInjection/DefaultConventionalRegistrar.cs b/src/Volo.Abp/Volo/DependencyInjection/DefaultConventionalRegistrar.cs index cd1e54e284..2a59e4450f 100644 --- a/src/Volo.Abp/Volo/DependencyInjection/DefaultConventionalRegistrar.cs +++ b/src/Volo.Abp/Volo/DependencyInjection/DefaultConventionalRegistrar.cs @@ -24,7 +24,7 @@ namespace Volo.DependencyInjection return; } - foreach (var serviceType in AutoRegistrationHelper.GetExposedServices(type)) + foreach (var serviceType in AutoRegistrationHelper.GetExposedServices(services, type)) { var serviceDescriptor = ServiceDescriptor.Describe(serviceType, type, lifeTime.Value); diff --git a/src/Volo.Abp/Volo/DependencyInjection/ExposeServicesAttribute.cs b/src/Volo.Abp/Volo/DependencyInjection/ExposeServicesAttribute.cs index 31e898ce2c..521e99cd5b 100644 --- a/src/Volo.Abp/Volo/DependencyInjection/ExposeServicesAttribute.cs +++ b/src/Volo.Abp/Volo/DependencyInjection/ExposeServicesAttribute.cs @@ -11,7 +11,7 @@ namespace Volo.DependencyInjection ExposedServiceTypes = exposedServiceTypes ?? new Type[0]; } - public Type[] GetExposedServiceTypes() + public Type[] GetExposedServiceTypes(Type targetType) { return ExposedServiceTypes; } diff --git a/src/Volo.Abp/Volo/DependencyInjection/IExposedServiceTypesProvider.cs b/src/Volo.Abp/Volo/DependencyInjection/IExposedServiceTypesProvider.cs index e78ddd2040..4a04d55af8 100644 --- a/src/Volo.Abp/Volo/DependencyInjection/IExposedServiceTypesProvider.cs +++ b/src/Volo.Abp/Volo/DependencyInjection/IExposedServiceTypesProvider.cs @@ -4,6 +4,6 @@ namespace Volo.DependencyInjection { public interface IExposedServiceTypesProvider { - Type[] GetExposedServiceTypes(); + Type[] GetExposedServiceTypes(Type targetType); } } diff --git a/src/Volo.Abp/Volo/DependencyInjection/IServiceExposingArgs.cs b/src/Volo.Abp/Volo/DependencyInjection/IServiceExposingArgs.cs new file mode 100644 index 0000000000..224f6ef0c5 --- /dev/null +++ b/src/Volo.Abp/Volo/DependencyInjection/IServiceExposingArgs.cs @@ -0,0 +1,12 @@ +using System; +using System.Collections.Generic; + +namespace Volo.DependencyInjection +{ + public interface IOnServiceExposingArgs + { + Type ImplementationType { get; } + + List ExposedTypes { get; } + } +} \ No newline at end of file diff --git a/src/Volo.Abp/Volo/DependencyInjection/OnServiceExposingArgs.cs b/src/Volo.Abp/Volo/DependencyInjection/OnServiceExposingArgs.cs new file mode 100644 index 0000000000..c422576833 --- /dev/null +++ b/src/Volo.Abp/Volo/DependencyInjection/OnServiceExposingArgs.cs @@ -0,0 +1,19 @@ +using System; +using System.Collections.Generic; +using JetBrains.Annotations; + +namespace Volo.DependencyInjection +{ + public class OnServiceExposingArgs : IOnServiceExposingArgs + { + public Type ImplementationType { get; } + + public List ExposedTypes { get; } + + public OnServiceExposingArgs([NotNull] Type implementationType, List exposedTypes) + { + ImplementationType = Check.NotNull(implementationType, nameof(implementationType)); + ExposedTypes = Check.NotNull(exposedTypes, nameof(exposedTypes)); + } + } +} \ No newline at end of file diff --git a/src/Volo.Abp/Volo/DependencyInjection/ServiceExposingActionList.cs b/src/Volo.Abp/Volo/DependencyInjection/ServiceExposingActionList.cs new file mode 100644 index 0000000000..97bc0622a7 --- /dev/null +++ b/src/Volo.Abp/Volo/DependencyInjection/ServiceExposingActionList.cs @@ -0,0 +1,10 @@ +using System; +using System.Collections.Generic; + +namespace Volo.DependencyInjection +{ + public class ServiceExposingActionList : List> + { + + } +} \ No newline at end of file diff --git a/test/Volo.Abp.AutoMapper.Tests/Volo/Abp/AutoMapper/SampleClasses/MyEntityToMyEntityDto2Mapper.cs b/test/Volo.Abp.AutoMapper.Tests/Volo/Abp/AutoMapper/SampleClasses/MyEntityToMyEntityDto2Mapper.cs index 4c8b3281bf..3b87d25552 100644 --- a/test/Volo.Abp.AutoMapper.Tests/Volo/Abp/AutoMapper/SampleClasses/MyEntityToMyEntityDto2Mapper.cs +++ b/test/Volo.Abp.AutoMapper.Tests/Volo/Abp/AutoMapper/SampleClasses/MyEntityToMyEntityDto2Mapper.cs @@ -3,7 +3,6 @@ using Volo.DependencyInjection; namespace Volo.Abp.AutoMapper.SampleClasses { - [ExposeServices(typeof(IObjectMapper))] public class MyEntityToMyEntityDto2Mapper : IObjectMapper, ITransientDependency { public MyEntityDto2 Map(MyEntity source) diff --git a/test/Volo.Abp.Tests/Volo/DependencyInjection/AutoRegistrationHelper_Tests.cs b/test/Volo.Abp.Tests/Volo/DependencyInjection/AutoRegistrationHelper_Tests.cs index 801d5733b0..d067be64fa 100644 --- a/test/Volo.Abp.Tests/Volo/DependencyInjection/AutoRegistrationHelper_Tests.cs +++ b/test/Volo.Abp.Tests/Volo/DependencyInjection/AutoRegistrationHelper_Tests.cs @@ -1,4 +1,5 @@ using System.Linq; +using Microsoft.Extensions.DependencyInjection; using Shouldly; using Xunit; @@ -11,7 +12,7 @@ namespace Volo.DependencyInjection { //Act - var exposedServices = AutoRegistrationHelper.GetExposedServices(typeof(DefaultDerivedService)).ToList(); + var exposedServices = AutoRegistrationHelper.GetExposedServices(new ServiceCollection(), typeof(DefaultDerivedService)).ToList(); //Assert @@ -26,7 +27,7 @@ namespace Volo.DependencyInjection { //Act - var exposedServices = AutoRegistrationHelper.GetExposedServices(typeof(ExplicitDerivedService)).ToList(); + var exposedServices = AutoRegistrationHelper.GetExposedServices(new ServiceCollection(), typeof(ExplicitDerivedService)).ToList(); //Assert