Browse Source

Merge pull request #10376 from iyilm4z/missing-dependency-attr-impl-for-mvc

Implemented missing DependencyAttribute business for AspNetCore
pull/10398/head
maliming 4 years ago
committed by GitHub
parent
commit
8ba028dd9a
No known key found for this signature in database GPG Key ID: 4AEE18F83AFDEB23
  1. 34
      framework/src/Volo.Abp.AspNetCore.Components/Volo/Abp/AspNetCore/Components/DependencyInjection/AbpWebAssemblyConventionalRegistrar.cs
  2. 41
      framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/DependencyInjection/AbpAspNetCoreMvcConventionalRegistrar.cs
  3. 36
      framework/src/Volo.Abp.AspNetCore.SignalR/Volo/Abp/AspNetCore/SignalR/AbpSignalRConventionalRegistrar.cs
  4. 18
      framework/src/Volo.Abp.AutoMapper/Volo/Abp/AutoMapper/AbpAutoMapperConventionalRegistrar.cs
  5. 23
      framework/src/Volo.Abp.BackgroundWorkers.Quartz/Volo/Abp/BackgroundWorkers/Quartz/AbpQuartzConventionalRegistrar.cs
  6. 100
      framework/src/Volo.Abp.Core/Volo/Abp/DependencyInjection/ConventionalRegistrarBase.cs
  7. 95
      framework/src/Volo.Abp.Core/Volo/Abp/DependencyInjection/DefaultConventionalRegistrar.cs
  8. 12
      framework/src/Volo.Abp.Ddd.Domain/Volo/Abp/Domain/Repositories/AbpRepositoryConventionalRegistrar.cs
  9. 38
      framework/src/Volo.Abp.FluentValidation/Volo/Abp/FluentValidation/AbpFluentValidationConventionalRegistrar.cs
  10. 27
      framework/src/Volo.Abp.MongoDB/Volo/Abp/MongoDB/DependencyInjection/AbpMongoDbConventionalRegistrar.cs
  11. 40
      framework/test/Volo.Abp.AspNetCore.Mvc.Tests/Volo/Abp/AspNetCore/Mvc/DependencyInjection/AbpAspNetCoreMvcConventionalRegistrar_Tests.cs
  12. 24
      framework/test/Volo.Abp.MongoDB.Tests/Volo/Abp/MongoDB/AbpMongoDbConventionalRegistrar_Tests.cs

34
framework/src/Volo.Abp.AspNetCore.Components/Volo/Abp/AspNetCore/Components/DependencyInjection/AbpWebAssemblyConventionalRegistrar.cs

@ -5,39 +5,21 @@ using Volo.Abp.DependencyInjection;
namespace Volo.Abp.AspNetCore.Components.DependencyInjection
{
public class AbpWebAssemblyConventionalRegistrar : ConventionalRegistrarBase
public class AbpWebAssemblyConventionalRegistrar : DefaultConventionalRegistrar
{
public override void AddType(IServiceCollection services, Type type)
protected override bool IsConventionalRegistrationDisabled(Type type)
{
if (IsConventionalRegistrationDisabled(type))
{
return;
}
if (!IsComponent(type))
{
return;
}
var serviceTypes = ExposedServiceExplorer.GetExposedServices(type);
TriggerServiceExposing(services, type, serviceTypes);
foreach (var serviceType in serviceTypes)
{
services.Add(
ServiceDescriptor.Describe(
serviceType,
type,
ServiceLifetime.Transient
)
);
}
return !IsComponent(type) || base.IsConventionalRegistrationDisabled(type);
}
private static bool IsComponent(Type type)
{
return typeof(ComponentBase).IsAssignableFrom(type);
}
protected override ServiceLifetime? GetDefaultLifeTimeOrNull(Type type)
{
return ServiceLifetime.Transient;
}
}
}

41
framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/DependencyInjection/AbpAspNetCoreMvcConventionalRegistrar.cs

@ -7,36 +7,11 @@ using Volo.Abp.DependencyInjection;
namespace Volo.Abp.AspNetCore.Mvc.DependencyInjection
{
public class AbpAspNetCoreMvcConventionalRegistrar : ConventionalRegistrarBase
public class AbpAspNetCoreMvcConventionalRegistrar : DefaultConventionalRegistrar
{
public override void AddType(IServiceCollection services, Type type)
protected override bool IsConventionalRegistrationDisabled(Type type)
{
if (IsConventionalRegistrationDisabled(type))
{
return;
}
if (!IsMvcService(type))
{
return;
}
var lifeTime = GetMvcServiceLifetime(type);
var serviceTypes = ExposedServiceExplorer.GetExposedServices(type);
TriggerServiceExposing(services, type, serviceTypes);
foreach (var serviceType in serviceTypes)
{
services.Add(
ServiceDescriptor.Describe(
serviceType,
type,
lifeTime
)
);
}
return !IsMvcService(type) || base.IsConventionalRegistrationDisabled(type);
}
protected virtual bool IsMvcService(Type type)
@ -46,11 +21,6 @@ namespace Volo.Abp.AspNetCore.Mvc.DependencyInjection
IsViewComponent(type);
}
protected virtual ServiceLifetime GetMvcServiceLifetime(Type type)
{
return ServiceLifetime.Transient;
}
private static bool IsPageModel(Type type)
{
return typeof(PageModel).IsAssignableFrom(type) || type.IsDefined(typeof(PageModelAttribute), true);
@ -65,5 +35,10 @@ namespace Volo.Abp.AspNetCore.Mvc.DependencyInjection
{
return typeof(ViewComponent).IsAssignableFrom(type) || type.IsDefined(typeof(ViewComponentAttribute), true);
}
protected override ServiceLifetime? GetDefaultLifeTimeOrNull(Type type)
{
return ServiceLifetime.Transient;
}
}
}

36
framework/src/Volo.Abp.AspNetCore.SignalR/Volo/Abp/AspNetCore/SignalR/AbpSignalRConventionalRegistrar.cs

@ -5,39 +5,21 @@ using Volo.Abp.DependencyInjection;
namespace Volo.Abp.AspNetCore.SignalR
{
public class AbpSignalRConventionalRegistrar : ConventionalRegistrarBase
public class AbpSignalRConventionalRegistrar : DefaultConventionalRegistrar
{
public override void AddType(IServiceCollection services, Type type)
protected override bool IsConventionalRegistrationDisabled(Type type)
{
if (IsConventionalRegistrationDisabled(type))
{
return;
}
if (!IsHub(type))
{
return;
}
var serviceTypes = ExposedServiceExplorer.GetExposedServices(type);
TriggerServiceExposing(services, type, serviceTypes);
foreach (var serviceType in serviceTypes)
{
services.Add(
ServiceDescriptor.Describe(
serviceType,
type,
ServiceLifetime.Transient
)
);
}
return !IsHub(type) || base.IsConventionalRegistrationDisabled(type);
}
private static bool IsHub(Type type)
{
return typeof(Hub).IsAssignableFrom(type);
}
protected override ServiceLifetime? GetDefaultLifeTimeOrNull(Type type)
{
return ServiceLifetime.Transient;
}
}
}

18
framework/src/Volo.Abp.AutoMapper/Volo/Abp/AutoMapper/AbpAutoMapperConventionalRegistrar.cs

@ -3,12 +3,11 @@ using System.Linq;
using AutoMapper;
using AutoMapper.Internal;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.DependencyInjection.Extensions;
using Volo.Abp.DependencyInjection;
namespace Volo.Abp.AutoMapper
{
public class AbpAutoMapperConventionalRegistrar : ConventionalRegistrarBase
public class AbpAutoMapperConventionalRegistrar : DefaultConventionalRegistrar
{
protected readonly Type[] OpenTypes = {
typeof(IValueResolver<,,>),
@ -18,17 +17,14 @@ namespace Volo.Abp.AutoMapper
typeof(IMappingAction<,>)
};
public override void AddType(IServiceCollection services, Type type)
protected override bool IsConventionalRegistrationDisabled(Type type)
{
if (IsConventionalRegistrationDisabled(type))
{
return;
}
return !OpenTypes.Any(type.ImplementsGenericInterface) || base.IsConventionalRegistrationDisabled(type);
}
if (type.IsClass && !type.IsAbstract && OpenTypes.Any(type.ImplementsGenericInterface))
{
services.TryAddTransient(type);
}
protected override ServiceLifetime? GetDefaultLifeTimeOrNull(Type type)
{
return ServiceLifetime.Transient;
}
}
}

23
framework/src/Volo.Abp.BackgroundWorkers.Quartz/Volo/Abp/BackgroundWorkers/Quartz/AbpQuartzConventionalRegistrar.cs

@ -1,27 +1,22 @@
using System;
using Microsoft.Extensions.DependencyInjection;
using System.Collections.Generic;
using Volo.Abp.DependencyInjection;
namespace Volo.Abp.BackgroundWorkers.Quartz
{
public class AbpQuartzConventionalRegistrar : DefaultConventionalRegistrar
{
public override void AddType(IServiceCollection services, Type type)
protected override bool IsConventionalRegistrationDisabled(Type type)
{
if (!typeof(IQuartzBackgroundWorker).IsAssignableFrom(type))
{
return;
}
var dependencyAttribute = GetDependencyAttributeOrNull(type);
var lifeTime = GetLifeTimeOrNull(type, dependencyAttribute);
return !typeof(IQuartzBackgroundWorker).IsAssignableFrom(type) || base.IsConventionalRegistrationDisabled(type);
}
if (lifeTime == null)
protected override List<Type> GetExposedServiceTypes(Type type)
{
return new List<Type>()
{
return;
}
services.Add(ServiceDescriptor.Describe(typeof(IQuartzBackgroundWorker), type, lifeTime.Value));
typeof(IQuartzBackgroundWorker)
};
}
}
}

100
framework/src/Volo.Abp.Core/Volo/Abp/DependencyInjection/ConventionalRegistrarBase.cs

@ -2,6 +2,7 @@
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using JetBrains.Annotations;
using Microsoft.Extensions.DependencyInjection;
using Volo.Abp.Reflection;
@ -50,5 +51,102 @@ namespace Volo.Abp.DependencyInjection
}
}
}
protected virtual DependencyAttribute GetDependencyAttributeOrNull(Type type)
{
return type.GetCustomAttribute<DependencyAttribute>(true);
}
protected virtual ServiceLifetime? GetLifeTimeOrNull(Type type, [CanBeNull] DependencyAttribute dependencyAttribute)
{
return dependencyAttribute?.Lifetime ?? GetServiceLifetimeFromClassHierarchy(type) ?? GetDefaultLifeTimeOrNull(type);
}
protected virtual ServiceLifetime? GetServiceLifetimeFromClassHierarchy(Type type)
{
if (typeof(ITransientDependency).GetTypeInfo().IsAssignableFrom(type))
{
return ServiceLifetime.Transient;
}
if (typeof(ISingletonDependency).GetTypeInfo().IsAssignableFrom(type))
{
return ServiceLifetime.Singleton;
}
if (typeof(IScopedDependency).GetTypeInfo().IsAssignableFrom(type))
{
return ServiceLifetime.Scoped;
}
return null;
}
protected virtual ServiceLifetime? GetDefaultLifeTimeOrNull(Type type)
{
return null;
}
protected virtual List<Type> GetExposedServiceTypes(Type type)
{
return ExposedServiceExplorer.GetExposedServices(type);
}
protected virtual ServiceDescriptor CreateServiceDescriptor(
Type implementationType,
Type exposingServiceType,
List<Type> allExposingServiceTypes,
ServiceLifetime lifeTime)
{
if (lifeTime.IsIn(ServiceLifetime.Singleton, ServiceLifetime.Scoped))
{
var redirectedType = GetRedirectedTypeOrNull(
implementationType,
exposingServiceType,
allExposingServiceTypes
);
if (redirectedType != null)
{
return ServiceDescriptor.Describe(
exposingServiceType,
provider => provider.GetService(redirectedType),
lifeTime
);
}
}
return ServiceDescriptor.Describe(
exposingServiceType,
implementationType,
lifeTime
);
}
protected virtual Type GetRedirectedTypeOrNull(
Type implementationType,
Type exposingServiceType,
List<Type> allExposingServiceTypes)
{
if (allExposingServiceTypes.Count < 2)
{
return null;
}
if (exposingServiceType == implementationType)
{
return null;
}
if (allExposingServiceTypes.Contains(implementationType))
{
return implementationType;
}
return allExposingServiceTypes.FirstOrDefault(
t => t != exposingServiceType && exposingServiceType.IsAssignableFrom(t)
);
}
}
}
}

95
framework/src/Volo.Abp.Core/Volo/Abp/DependencyInjection/DefaultConventionalRegistrar.cs

@ -1,8 +1,4 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using JetBrains.Annotations;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.DependencyInjection.Extensions;
@ -53,96 +49,5 @@ namespace Volo.Abp.DependencyInjection
}
}
}
protected virtual List<Type> GetExposedServiceTypes(Type type)
{
return ExposedServiceExplorer.GetExposedServices(type);
}
protected virtual ServiceDescriptor CreateServiceDescriptor(
Type implementationType,
Type exposingServiceType,
List<Type> allExposingServiceTypes,
ServiceLifetime lifeTime)
{
if (lifeTime.IsIn(ServiceLifetime.Singleton, ServiceLifetime.Scoped))
{
var redirectedType = GetRedirectedTypeOrNull(
implementationType,
exposingServiceType,
allExposingServiceTypes
);
if (redirectedType != null)
{
return ServiceDescriptor.Describe(
exposingServiceType,
provider => provider.GetService(redirectedType),
lifeTime
);
}
}
return ServiceDescriptor.Describe(
exposingServiceType,
implementationType,
lifeTime
);
}
protected virtual Type GetRedirectedTypeOrNull(
Type implementationType,
Type exposingServiceType,
List<Type> allExposingServiceTypes)
{
if (allExposingServiceTypes.Count < 2)
{
return null;
}
if (exposingServiceType == implementationType)
{
return null;
}
if (allExposingServiceTypes.Contains(implementationType))
{
return implementationType;
}
return allExposingServiceTypes.FirstOrDefault(
t => t != exposingServiceType && exposingServiceType.IsAssignableFrom(t)
);
}
protected virtual DependencyAttribute GetDependencyAttributeOrNull(Type type)
{
return type.GetCustomAttribute<DependencyAttribute>(true);
}
protected virtual ServiceLifetime? GetLifeTimeOrNull(Type type, [CanBeNull] DependencyAttribute dependencyAttribute)
{
return dependencyAttribute?.Lifetime ?? GetServiceLifetimeFromClassHierarchy(type);
}
protected virtual ServiceLifetime? GetServiceLifetimeFromClassHierarchy(Type type)
{
if (typeof(ITransientDependency).GetTypeInfo().IsAssignableFrom(type))
{
return ServiceLifetime.Transient;
}
if (typeof(ISingletonDependency).GetTypeInfo().IsAssignableFrom(type))
{
return ServiceLifetime.Singleton;
}
if (typeof(IScopedDependency).GetTypeInfo().IsAssignableFrom(type))
{
return ServiceLifetime.Scoped;
}
return null;
}
}
}

12
framework/src/Volo.Abp.Ddd.Domain/Volo/Abp/Domain/Repositories/AbpRepositoryConventionalRegistrar.cs

@ -15,12 +15,7 @@ namespace Volo.Abp.Domain.Repositories
protected override bool IsConventionalRegistrationDisabled(Type type)
{
if (!typeof(IRepository).IsAssignableFrom(type))
{
return true;
}
return base.IsConventionalRegistrationDisabled(type);
return !typeof(IRepository).IsAssignableFrom(type) || base.IsConventionalRegistrationDisabled(type);
}
protected override List<Type> GetExposedServiceTypes(Type type)
@ -35,10 +30,9 @@ namespace Volo.Abp.Domain.Repositories
.ToList();
}
protected override ServiceLifetime? GetServiceLifetimeFromClassHierarchy(Type type)
protected override ServiceLifetime? GetDefaultLifeTimeOrNull(Type type)
{
return base.GetServiceLifetimeFromClassHierarchy(type) ??
ServiceLifetime.Transient;
return ServiceLifetime.Transient;
}
}
}

38
framework/src/Volo.Abp.FluentValidation/Volo/Abp/FluentValidation/AbpFluentValidationConventionalRegistrar.cs

@ -1,39 +1,31 @@
using System;
using System.Collections.Generic;
using System.Linq;
using FluentValidation;
using Microsoft.Extensions.DependencyInjection;
using Volo.Abp.DependencyInjection;
namespace Volo.Abp.FluentValidation
{
public class AbpFluentValidationConventionalRegistrar : ConventionalRegistrarBase
public class AbpFluentValidationConventionalRegistrar : DefaultConventionalRegistrar
{
public override void AddType(IServiceCollection services, Type type)
protected override bool IsConventionalRegistrationDisabled(Type type)
{
if (IsConventionalRegistrationDisabled(type))
{
return;
}
return !type.GetInterfaces().Any(x => x.IsGenericType && x.GetGenericTypeDefinition() == typeof(IValidator<>)) ||
base.IsConventionalRegistrationDisabled(type);
}
if (!typeof(IValidator).IsAssignableFrom(type))
{
return;
}
protected override ServiceLifetime? GetDefaultLifeTimeOrNull(Type type)
{
return ServiceLifetime.Transient;
}
var validatingType = GetFirstGenericArgumentOrNull(type, 1);
if (validatingType == null)
protected override List<Type> GetExposedServiceTypes(Type type)
{
return new List<Type>()
{
return;
}
var serviceType = typeof(IValidator<>).MakeGenericType(validatingType);
TriggerServiceExposing(services, type, new List<Type>{ serviceType });
services.AddTransient(
serviceType,
type
);
typeof(IValidator<>).MakeGenericType(GetFirstGenericArgumentOrNull(type, 1))
};
}
private static Type GetFirstGenericArgumentOrNull(Type type, int depth)

27
framework/src/Volo.Abp.MongoDB/Volo/Abp/MongoDB/DependencyInjection/AbpMongoDbConventionalRegistrar.cs

@ -1,29 +1,28 @@
using System;
using System.Reflection;
using System.Collections.Generic;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.DependencyInjection.Extensions;
using Volo.Abp.DependencyInjection;
namespace Volo.Abp.MongoDB.DependencyInjection
{
public class AbpMongoDbConventionalRegistrar : DefaultConventionalRegistrar
{
public override void AddType(IServiceCollection services, Type type)
protected override bool IsConventionalRegistrationDisabled(Type type)
{
if (!typeof(IAbpMongoDbContext).IsAssignableFrom(type) || type == typeof(AbpMongoDbContext))
{
return;
}
var dependencyAttribute = GetDependencyAttributeOrNull(type);
var lifeTime = GetLifeTimeOrNull(type, dependencyAttribute);
return !typeof(IAbpMongoDbContext).IsAssignableFrom(type) || type == typeof(AbpMongoDbContext) || base.IsConventionalRegistrationDisabled(type);
}
if (lifeTime == null)
protected override List<Type> GetExposedServiceTypes(Type type)
{
return new List<Type>()
{
return;
}
typeof(IAbpMongoDbContext)
};
}
services.Add(ServiceDescriptor.Describe(typeof(IAbpMongoDbContext), type, ServiceLifetime.Transient));
protected override ServiceLifetime? GetDefaultLifeTimeOrNull(Type type)
{
return ServiceLifetime.Transient;
}
}
}

40
framework/test/Volo.Abp.AspNetCore.Mvc.Tests/Volo/Abp/AspNetCore/Mvc/DependencyInjection/AbpAspNetCoreMvcConventionalRegistrar_Tests.cs

@ -1,7 +1,4 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Linq;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.RazorPages;
using Microsoft.Extensions.DependencyInjection;
@ -26,15 +23,35 @@ namespace Volo.Abp.AspNetCore.Mvc.DependencyInjection
services.AddTypes(typeof(My_Test_PageModel), typeof(My_Test_Controller), typeof(My_Test_ViewComponent));
//Assert
services.ShouldContainTransient(typeof(My_Test_PageModel));
services.ShouldContainTransient(typeof(My_Test_Controller));
services.ShouldContainTransient(typeof(My_Test_ViewComponent));
services.ShouldContainTransient(typeof(My_Test_PageModel));
services.ShouldContainTransient(typeof(My_Test_Controller));
services.ShouldContainTransient(typeof(My_Test_ViewComponent));
var serviceProvider = services.BuildServiceProvider();
serviceProvider.GetServices<My_Test_PageModel>().Count().ShouldBe(1);
serviceProvider.GetServices<My_Test_Controller>().Count().ShouldBe(1);
serviceProvider.GetServices<My_Test_ViewComponent>().Count().ShouldBe(1);
}
[Fact]
public void Should_Replace_Registered_Mvc_Service()
{
//Arrange
var services = new ServiceCollection();
//Act
services.AddConventionalRegistrar(new DefaultConventionalRegistrar());
services.AddConventionalRegistrar(new AbpAspNetCoreMvcConventionalRegistrar());
services.AddTypes(typeof(My_Second_Test_ViewComponent), typeof(My_Third_Test_ViewComponent));
//Assert
services.ShouldContainTransient(typeof(My_Second_Test_ViewComponent), typeof(My_Third_Test_ViewComponent));
services.ShouldNotContainService(typeof(My_Third_Test_ViewComponent));
var serviceProvider = services.BuildServiceProvider();
serviceProvider.GetServices<My_Second_Test_ViewComponent>().Count().ShouldBe(1);
}
}
public class My_Test_PageModel : PageModel
@ -49,6 +66,15 @@ namespace Volo.Abp.AspNetCore.Mvc.DependencyInjection
public class My_Test_ViewComponent : ViewComponent
{
}
public class My_Second_Test_ViewComponent : ViewComponent
{
}
[Dependency(ReplaceServices = true)]
[ExposeServices(typeof(My_Second_Test_ViewComponent))]
public class My_Third_Test_ViewComponent : My_Second_Test_ViewComponent
{
}
}

24
framework/test/Volo.Abp.MongoDB.Tests/Volo/Abp/MongoDB/AbpMongoDbConventionalRegistrar_Tests.cs

@ -0,0 +1,24 @@
using Microsoft.Extensions.DependencyInjection;
using Shouldly;
using Volo.Abp.MongoDB.TestApp.FourthContext;
using Volo.Abp.MongoDB.TestApp.SecondContext;
using Volo.Abp.MongoDB.TestApp.ThirdDbContext;
using Volo.Abp.TestApp.MongoDB;
using Xunit;
namespace Volo.Abp.MongoDB
{
[Collection(MongoTestCollection.Name)]
public class AbpMongoDbConventionalRegistrar_Tests : MongoDbTestBase
{
[Fact]
public void All_AbpMongoDbContext_Should_Exposed_IAbpMongoDbContext_Service()
{
var abpMongoDbContext = ServiceProvider.GetServices<IAbpMongoDbContext>();
abpMongoDbContext.ShouldContain(x => x is TestAppMongoDbContext);
abpMongoDbContext.ShouldContain(x => x is SecondDbContext);
abpMongoDbContext.ShouldContain(x => x is ThirdDbContext);
abpMongoDbContext.ShouldContain(x => x is FourthDbContext);
}
}
}
Loading…
Cancel
Save