Browse Source

#38 Create convention to expose service types.

pull/96/head
Halil İbrahim Kalkan 9 years ago
parent
commit
3054dbf572
  1. 3
      src/Volo.Abp.Autofac/Autofac/Builder/AbpRegistrationBuilderExtensions.cs
  2. 3
      src/Volo.Abp/Microsoft/Extensions/DependencyInjection/OnServiceRegistredArgs.cs
  3. 32
      src/Volo.Abp/Microsoft/Extensions/DependencyInjection/ServiceCollectionRegistrationActionExtensions.cs
  4. 30
      src/Volo.Abp/Volo/Abp/AbpKernelModule.cs
  5. 18
      src/Volo.Abp/Volo/Abp/ObjectMapping/IObjectMapper.cs
  6. 36
      src/Volo.Abp/Volo/Abp/Reflection/ReflectionHelper.cs
  7. 24
      src/Volo.Abp/Volo/DependencyInjection/AutoRegistrationHelper.cs
  8. 2
      src/Volo.Abp/Volo/DependencyInjection/DefaultConventionalRegistrar.cs
  9. 2
      src/Volo.Abp/Volo/DependencyInjection/ExposeServicesAttribute.cs
  10. 2
      src/Volo.Abp/Volo/DependencyInjection/IExposedServiceTypesProvider.cs
  11. 12
      src/Volo.Abp/Volo/DependencyInjection/IServiceExposingArgs.cs
  12. 19
      src/Volo.Abp/Volo/DependencyInjection/OnServiceExposingArgs.cs
  13. 10
      src/Volo.Abp/Volo/DependencyInjection/ServiceExposingActionList.cs
  14. 1
      test/Volo.Abp.AutoMapper.Tests/Volo/Abp/AutoMapper/SampleClasses/MyEntityToMyEntityDto2Mapper.cs
  15. 5
      test/Volo.Abp.Tests/Volo/DependencyInjection/AutoRegistrationHelper_Tests.cs

3
src/Volo.Abp.Autofac/Autofac/Builder/AbpRegistrationBuilderExtensions.cs

@ -38,8 +38,7 @@ namespace Autofac.Builder
private static IRegistrationBuilder<TLimit, TConcreteReflectionActivatorData, TRegistrationStyle> AddInterceptors<TLimit, TConcreteReflectionActivatorData, TRegistrationStyle>(
this IRegistrationBuilder<TLimit, TConcreteReflectionActivatorData, TRegistrationStyle> registrationBuilder,
Type[] interceptors
)
Type[] interceptors)
where TConcreteReflectionActivatorData : ConcreteReflectionActivatorData
{
var serviceType = registrationBuilder.RegistrationData.Services.OfType<IServiceWithType>().FirstOrDefault()?.ServiceType;

3
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));

32
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<IObjectAccessor<ServiceRegistrationActionList>>()?.Value;
if (registrationActionList == null)
var actionList = services.GetSingletonInstanceOrNull<IObjectAccessor<ServiceRegistrationActionList>>()?.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<IOnServiceExposingArgs> 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<IObjectAccessor<ServiceExposingActionList>>()?.Value;
if (actionList == null)
{
actionList = new ServiceExposingActionList();
services.AddObjectAccessor(actionList);
}
return actionList;
}
}
}

30
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<UnitOfWorkInterceptor>();
}
});
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<ObjectAccessor<IServiceProvider>>().Value = context.ServiceProvider;
}
private static void RegisterUnitOfWorkInterceptor(IOnServiceRegistredArgs registration)
{
if (typeof(IApplicationService).GetTypeInfo().IsAssignableFrom(registration.ImplementationType))
{
registration.Interceptors.Add<UnitOfWorkInterceptor>();
}
}
}
}

18
src/Volo.Abp/Volo/Abp/ObjectMapping/IObjectMapper.cs

@ -1,7 +1,7 @@
namespace Volo.Abp.ObjectMapping
{
/// <summary>
/// Defines a simple interface to map objects.
/// Defines a simple interface to automatically map objects.
/// </summary>
public interface IObjectMapper
{
@ -24,10 +24,26 @@
TDestination Map<TSource, TDestination>(TSource source, TDestination destination);
}
/// <summary>
/// Maps an object to another.
/// Implement this interface to override object to object mapping for specific types.
/// </summary>
/// <typeparam name="TSource"></typeparam>
/// <typeparam name="TDestination"></typeparam>
public interface IObjectMapper<in TSource, TDestination>
{
/// <summary>
/// Converts an object to another. Creates a new object of <see cref="TDestination"/>.
/// </summary>
/// <param name="source">Source object</param>
TDestination Map(TSource source);
/// <summary>
/// Execute a mapping from the source object to the existing destination object
/// </summary>
/// <param name="source">Source object</param>
/// <param name="destination">Destination object</param>
/// <returns>Returns the same <see cref="destination"/> object after mapping operation</returns>
TDestination Map(TSource source, TDestination destination);
}
}

36
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
/// <summary>
/// Checks whether <paramref name="givenType"/> implements/inherits <paramref name="genericType"/>.
/// </summary>
@ -34,5 +37,38 @@ namespace Volo.Abp.Reflection
return IsAssignableToGenericType(givenTypeInfo.BaseType, genericType);
}
//TODO: Summary
public static List<Type> GetImplementedGenericTypes(Type givenType, Type genericType)
{
var result = new List<Type>();
AddImplementedGenericTypes(result, givenType, genericType);
return result;
}
private static void AddImplementedGenericTypes(List<Type> 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);
}
}
}

24
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<Type> GetExposedServices(Type type)
public static IEnumerable<Type> GetExposedServices(IServiceCollection services, Type type)
{
var typeInfo = type.GetTypeInfo();
var customExposedServices = typeInfo
.GetCustomAttributes()
.OfType<IExposedServiceTypesProvider>()
.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<Type> GetDefaultExposedServices(Type type, bool includeSelf = true)
private static IEnumerable<Type> GetDefaultExposedServices(IServiceCollection services, Type type)
{
var serviceTypes = new List<Type>();
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;
}
}

2
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);

2
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;
}

2
src/Volo.Abp/Volo/DependencyInjection/IExposedServiceTypesProvider.cs

@ -4,6 +4,6 @@ namespace Volo.DependencyInjection
{
public interface IExposedServiceTypesProvider
{
Type[] GetExposedServiceTypes();
Type[] GetExposedServiceTypes(Type targetType);
}
}

12
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<Type> ExposedTypes { get; }
}
}

19
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<Type> ExposedTypes { get; }
public OnServiceExposingArgs([NotNull] Type implementationType, List<Type> exposedTypes)
{
ImplementationType = Check.NotNull(implementationType, nameof(implementationType));
ExposedTypes = Check.NotNull(exposedTypes, nameof(exposedTypes));
}
}
}

10
src/Volo.Abp/Volo/DependencyInjection/ServiceExposingActionList.cs

@ -0,0 +1,10 @@
using System;
using System.Collections.Generic;
namespace Volo.DependencyInjection
{
public class ServiceExposingActionList : List<Action<IOnServiceExposingArgs>>
{
}
}

1
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<MyEntity, MyEntityDto2>))]
public class MyEntityToMyEntityDto2Mapper : IObjectMapper<MyEntity, MyEntityDto2>, ITransientDependency
{
public MyEntityDto2 Map(MyEntity source)

5
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

Loading…
Cancel
Save