Browse Source

Introduce AdditionalModuleAssemblyAttribute to define additional assemblies to be part of a module

pull/17026/head
Halil İbrahim Kalkan 3 years ago
parent
commit
d46ba3463f
  1. 4
      framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/ApplicationPartSorter.cs
  2. 2
      framework/src/Volo.Abp.Autofac/Autofac/Builder/AbpRegistrationBuilderExtensions.cs
  3. 26
      framework/src/Volo.Abp.Core/Volo/Abp/Modularity/AbpModuleDescriptor.cs
  4. 24
      framework/src/Volo.Abp.Core/Volo/Abp/Modularity/AdditionalModuleAssemblyAttribute.cs
  5. 4
      framework/src/Volo.Abp.Core/Volo/Abp/Modularity/DependsOnAttribute.cs
  6. 23
      framework/src/Volo.Abp.Core/Volo/Abp/Modularity/IAbpModuleDescriptor.cs
  7. 8
      framework/src/Volo.Abp.Core/Volo/Abp/Modularity/IAdditionalModuleAssemblyProvider.cs
  8. 5
      framework/test/Volo.Abp.Core.Tests/Volo/Abp/Modularity/ModuleLoader_Tests.cs

4
framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/ApplicationPartSorter.cs

@ -125,7 +125,7 @@ public static class ApplicationPartSorter
var moduleDependedAssemblies = moduleDescriptor var moduleDependedAssemblies = moduleDescriptor
.Dependencies .Dependencies
.Select(d => d.Assembly) .SelectMany(d => d.AllAssemblies)
.ToArray(); .ToArray();
return partManager.ApplicationParts return partManager.ApplicationParts
@ -161,6 +161,6 @@ public static class ApplicationPartSorter
{ {
return moduleContainer return moduleContainer
.Modules .Modules
.FirstOrDefault(m => m.Assembly == assembly); .FirstOrDefault(m => m.AllAssemblies.Contains(assembly));
} }
} }

2
framework/src/Volo.Abp.Autofac/Autofac/Builder/AbpRegistrationBuilderExtensions.cs

@ -69,7 +69,7 @@ public static class AbpRegistrationBuilderExtensions
where TActivatorData : ReflectionActivatorData where TActivatorData : ReflectionActivatorData
{ {
// Enable Property Injection only for types in an assembly containing an AbpModule and without a DisablePropertyInjection attribute on class or properties. // Enable Property Injection only for types in an assembly containing an AbpModule and without a DisablePropertyInjection attribute on class or properties.
if (moduleContainer.Modules.Any(m => m.Assembly == implementationType.Assembly) && if (moduleContainer.Modules.Any(m => m.AllAssemblies.Contains(implementationType.Assembly)) &&
implementationType.GetCustomAttributes(typeof(DisablePropertyInjectionAttribute), true).IsNullOrEmpty()) implementationType.GetCustomAttributes(typeof(DisablePropertyInjectionAttribute), true).IsNullOrEmpty())
{ {
registrationBuilder = registrationBuilder.PropertiesAutowired(new AbpPropertySelector(false)); registrationBuilder = registrationBuilder.PropertiesAutowired(new AbpPropertySelector(false));

26
framework/src/Volo.Abp.Core/Volo/Abp/Modularity/AbpModuleDescriptor.cs

@ -1,6 +1,7 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Collections.Immutable; using System.Collections.Immutable;
using System.Linq;
using System.Reflection; using System.Reflection;
using JetBrains.Annotations; using JetBrains.Annotations;
@ -11,6 +12,8 @@ public class AbpModuleDescriptor : IAbpModuleDescriptor
public Type Type { get; } public Type Type { get; }
public Assembly Assembly { get; } public Assembly Assembly { get; }
public List<Assembly> AllAssemblies { get; }
public IAbpModule Instance { get; } public IAbpModule Instance { get; }
@ -26,6 +29,7 @@ public class AbpModuleDescriptor : IAbpModuleDescriptor
{ {
Check.NotNull(type, nameof(type)); Check.NotNull(type, nameof(type));
Check.NotNull(instance, nameof(instance)); Check.NotNull(instance, nameof(instance));
AbpModule.CheckAbpModuleType(type);
if (!type.GetTypeInfo().IsAssignableFrom(instance.GetType())) if (!type.GetTypeInfo().IsAssignableFrom(instance.GetType()))
{ {
@ -34,6 +38,7 @@ public class AbpModuleDescriptor : IAbpModuleDescriptor
Type = type; Type = type;
Assembly = type.Assembly; Assembly = type.Assembly;
AllAssemblies = CreateAllAssembliesList(type);
Instance = instance; Instance = instance;
IsLoadedAsPlugIn = isLoadedAsPlugIn; IsLoadedAsPlugIn = isLoadedAsPlugIn;
@ -49,4 +54,25 @@ public class AbpModuleDescriptor : IAbpModuleDescriptor
{ {
return $"[AbpModuleDescriptor {Type.FullName}]"; return $"[AbpModuleDescriptor {Type.FullName}]";
} }
private static List<Assembly> CreateAllAssembliesList(Type moduleType)
{
var assemblies = new List<Assembly>();
var additionalAssemblyDescriptors = moduleType
.GetCustomAttributes()
.OfType<IAdditionalModuleAssemblyProvider>();
foreach (var descriptor in additionalAssemblyDescriptors)
{
foreach (var assembly in descriptor.GetAssemblies())
{
assemblies.AddIfNotContains(assembly);
}
}
assemblies.Add(moduleType.Assembly);
return assemblies;
}
} }

24
framework/src/Volo.Abp.Core/Volo/Abp/Modularity/AdditionalModuleAssemblyAttribute.cs

@ -0,0 +1,24 @@
using System;
using System.Linq;
using System.Reflection;
namespace Volo.Abp.Modularity;
/// <summary>
/// Used to define additional assemblies for a module.
/// </summary>
[AttributeUsage(AttributeTargets.Class, AllowMultiple = true)]
public class AdditionalModuleAssemblyAttribute : Attribute, IAdditionalModuleAssemblyProvider
{
public Type[] TypesInAssemblies { get; }
public AdditionalModuleAssemblyAttribute(params Type[]? typesInAssemblies)
{
TypesInAssemblies = typesInAssemblies ?? Type.EmptyTypes;
}
public virtual Assembly[] GetAssemblies()
{
return TypesInAssemblies.Select(t => t.Assembly).Distinct().ToArray();
}
}

4
framework/src/Volo.Abp.Core/Volo/Abp/Modularity/DependsOnAttribute.cs

@ -1,5 +1,4 @@
using System; using System;
using JetBrains.Annotations;
namespace Volo.Abp.Modularity; namespace Volo.Abp.Modularity;
@ -9,12 +8,11 @@ namespace Volo.Abp.Modularity;
[AttributeUsage(AttributeTargets.Class, AllowMultiple = true)] [AttributeUsage(AttributeTargets.Class, AllowMultiple = true)]
public class DependsOnAttribute : Attribute, IDependedTypesProvider public class DependsOnAttribute : Attribute, IDependedTypesProvider
{ {
[NotNull]
public Type[] DependedTypes { get; } public Type[] DependedTypes { get; }
public DependsOnAttribute(params Type[]? dependedTypes) public DependsOnAttribute(params Type[]? dependedTypes)
{ {
DependedTypes = dependedTypes ?? new Type[0]; DependedTypes = dependedTypes ?? Type.EmptyTypes;
} }
public virtual Type[] GetDependedTypes() public virtual Type[] GetDependedTypes()

23
framework/src/Volo.Abp.Core/Volo/Abp/Modularity/IAbpModuleDescriptor.cs

@ -6,13 +6,36 @@ namespace Volo.Abp.Modularity;
public interface IAbpModuleDescriptor public interface IAbpModuleDescriptor
{ {
/// <summary>
/// Type of the module class.
/// </summary>
Type Type { get; } Type Type { get; }
/// <summary>
/// Main assembly that defines the module <see cref="Type"/>.
/// </summary>
Assembly Assembly { get; } Assembly Assembly { get; }
/// <summary>
/// All the assemblies of the module.
/// Includes the main <see cref="Assembly"/> and other assemblies defined
/// on the module <see cref="Type"/> using the <see cref="AdditionalModuleAssemblyAttribute"/> attribute.
/// </summary>
List<Assembly> AllAssemblies { get; }
/// <summary>
/// The instance of the module class (singleton).
/// </summary>
IAbpModule Instance { get; } IAbpModule Instance { get; }
/// <summary>
/// Is this module loaded as a plug-in?
/// </summary>
bool IsLoadedAsPlugIn { get; } bool IsLoadedAsPlugIn { get; }
/// <summary>
/// Modules on which this module depends on.
/// A module can depend on another module using the <see cref="DependsOnAttribute"/> attribute.
/// </summary>
IReadOnlyList<IAbpModuleDescriptor> Dependencies { get; } IReadOnlyList<IAbpModuleDescriptor> Dependencies { get; }
} }

8
framework/src/Volo.Abp.Core/Volo/Abp/Modularity/IAdditionalModuleAssemblyProvider.cs

@ -0,0 +1,8 @@
using System.Reflection;
namespace Volo.Abp.Modularity;
public interface IAdditionalModuleAssemblyProvider
{
Assembly[] GetAssemblies();
}

5
framework/test/Volo.Abp.Core.Tests/Volo/Abp/Modularity/ModuleLoader_Tests.cs

@ -21,9 +21,14 @@ public class ModuleLoader_Tests
modules.Length.ShouldBe(2); modules.Length.ShouldBe(2);
modules[0].Type.ShouldBe(typeof(IndependentEmptyModule)); modules[0].Type.ShouldBe(typeof(IndependentEmptyModule));
modules[1].Type.ShouldBe(typeof(MyStartupModule)); modules[1].Type.ShouldBe(typeof(MyStartupModule));
modules[1].Assembly.ShouldBe(typeof(MyStartupModule).Assembly);
modules[1].AllAssemblies.Count.ShouldBe(2);
modules[1].AllAssemblies[0].ShouldBe(typeof(IAbpApplication).Assembly);
modules[1].AllAssemblies[1].ShouldBe(typeof(MyStartupModule).Assembly);
} }
[DependsOn(typeof(IndependentEmptyModule))] [DependsOn(typeof(IndependentEmptyModule))]
[AdditionalModuleAssembly(typeof(IAbpApplication))]
public class MyStartupModule : AbpModule public class MyStartupModule : AbpModule
{ {
public override void ConfigureServices(ServiceConfigurationContext context) public override void ConfigureServices(ServiceConfigurationContext context)

Loading…
Cancel
Save