diff --git a/docs/en/Module-Development-Basics.md b/docs/en/Module-Development-Basics.md
index dfce0bf4b2..915535906e 100644
--- a/docs/en/Module-Development-Basics.md
+++ b/docs/en/Module-Development-Basics.md
@@ -147,7 +147,7 @@ Lastly, you can override ``OnApplicationShutdown`` method if you want to execute
## Module Dependencies
-In a modular application, it's not unusual for one module to depend upon another module(s). An Abp module must declare ``[DependsOn]`` attribute if it does have a dependency upon another module, as shown below:
+In a modular application, it's not unusual for one module to depend upon another module(s). An ABP module must declare ``[DependsOn]`` attribute if it does have a dependency upon another module, as shown below:
````C#
[DependsOn(typeof(AbpAspNetCoreMvcModule))]
@@ -162,6 +162,25 @@ You can use multiple ``DependsOn`` attribute or pass multiple module types to a
A depended module may depend on another module, but you only need to define your direct dependencies. ABP investigates the dependency graph for the application at startup and initializes/shutdowns modules in the correct order.
+## Additional Module Assemblies
+
+ABP automatically registers all the services of your module to the [dependency injection](Dependency-Injection.md) system. It finds the service types by scanning types in the assembly that defines your module class. That assembly is considered as the main assembly of your module.
+
+Typically, every assembly contains a separate module class definition. Then modules depends on each other using the `DependsOn` attribute as explained in the previous section. However, in some rare cases, your module may be consisting of multiple assemblies, and only one of them defines a module class, and you want to make the other assemblies parts of your module. In that case, you can use the `AdditionalAssembly` attribute as shown below:
+
+````csharp
+[DependsOn(...)] // Your module dependencies as you normally do
+[AdditionalAssembly(typeof(BlogService))]
+public class BlogModule
+{
+ //...
+}
+````
+
+In this example, we assume that the `BlogService` class is inside one assembly (`csproj`) and the `BlogModule` class is inside another assembly (`csproj`). With the `AdditionalAssembly` definition, ABP will load the assembly containing the `BlogService` class as a part of the blog module.
+
+> WARNING: If you need to use the `AdditionalAssembly`, be sure that you don't design your system in a wrong way. With this example above, `BlogService` class' assembly should normally have its own module class and the `BlogModule` should depend on it using the `DependsOn` attribute. Do not use the `AdditionalAssembly` attribute when you can use the `DependsOn` attribute.
+
## Framework Modules vs Application Modules
There are **two types of modules.** They don't have any structural difference but categorized by functionality and purpose:
diff --git a/framework/src/Volo.Abp.Core/Volo/Abp/Modularity/AdditionalModuleAssemblyAttribute.cs b/framework/src/Volo.Abp.Core/Volo/Abp/Modularity/AdditionalAssemblyAttribute.cs
similarity index 74%
rename from framework/src/Volo.Abp.Core/Volo/Abp/Modularity/AdditionalModuleAssemblyAttribute.cs
rename to framework/src/Volo.Abp.Core/Volo/Abp/Modularity/AdditionalAssemblyAttribute.cs
index 4ae1be015e..ac4165f85e 100644
--- a/framework/src/Volo.Abp.Core/Volo/Abp/Modularity/AdditionalModuleAssemblyAttribute.cs
+++ b/framework/src/Volo.Abp.Core/Volo/Abp/Modularity/AdditionalAssemblyAttribute.cs
@@ -8,11 +8,11 @@ namespace Volo.Abp.Modularity;
/// Used to define additional assemblies for a module.
///
[AttributeUsage(AttributeTargets.Class, AllowMultiple = true)]
-public class AdditionalModuleAssemblyAttribute : Attribute, IAdditionalModuleAssemblyProvider
+public class AdditionalAssemblyAttribute : Attribute, IAdditionalModuleAssemblyProvider
{
public Type[] TypesInAssemblies { get; }
- public AdditionalModuleAssemblyAttribute(params Type[]? typesInAssemblies)
+ public AdditionalAssemblyAttribute(params Type[]? typesInAssemblies)
{
TypesInAssemblies = typesInAssemblies ?? Type.EmptyTypes;
}
diff --git a/framework/src/Volo.Abp.Core/Volo/Abp/Modularity/IAbpModuleDescriptor.cs b/framework/src/Volo.Abp.Core/Volo/Abp/Modularity/IAbpModuleDescriptor.cs
index 6b0a7214af..472009bfb3 100644
--- a/framework/src/Volo.Abp.Core/Volo/Abp/Modularity/IAbpModuleDescriptor.cs
+++ b/framework/src/Volo.Abp.Core/Volo/Abp/Modularity/IAbpModuleDescriptor.cs
@@ -19,7 +19,7 @@ public interface IAbpModuleDescriptor
///
/// All the assemblies of the module.
/// Includes the main and other assemblies defined
- /// on the module using the attribute.
+ /// on the module using the attribute.
///
List AllAssemblies { get; }
diff --git a/framework/test/Volo.Abp.Core.Tests/Volo/Abp/Modularity/ModuleLoader_Tests.cs b/framework/test/Volo.Abp.Core.Tests/Volo/Abp/Modularity/ModuleLoader_Tests.cs
index 52cc7f7b70..d06025302d 100644
--- a/framework/test/Volo.Abp.Core.Tests/Volo/Abp/Modularity/ModuleLoader_Tests.cs
+++ b/framework/test/Volo.Abp.Core.Tests/Volo/Abp/Modularity/ModuleLoader_Tests.cs
@@ -28,7 +28,7 @@ public class ModuleLoader_Tests
}
[DependsOn(typeof(IndependentEmptyModule))]
- [AdditionalModuleAssembly(typeof(IAbpApplication))]
+ [AdditionalAssembly(typeof(IAbpApplication))]
public class MyStartupModule : AbpModule
{
public override void ConfigureServices(ServiceConfigurationContext context)
diff --git a/framework/test/Volo.Abp.Core.Tests/Volo/Abp/Reflection/AssemblyFinder_Tests.cs b/framework/test/Volo.Abp.Core.Tests/Volo/Abp/Reflection/AssemblyFinder_Tests.cs
index 2ba02eee6b..f3086dcb8c 100644
--- a/framework/test/Volo.Abp.Core.Tests/Volo/Abp/Reflection/AssemblyFinder_Tests.cs
+++ b/framework/test/Volo.Abp.Core.Tests/Volo/Abp/Reflection/AssemblyFinder_Tests.cs
@@ -1,6 +1,7 @@
using System;
using System.Collections.Generic;
using System.Linq;
+using System.Reflection;
using NSubstitute;
using Shouldly;
using Volo.Abp.Modularity;
@@ -50,6 +51,7 @@ public class AssemblyFinder_Tests
{
var moduleDescriptor = Substitute.For();
moduleDescriptor.Type.Returns(moduleType);
+ moduleDescriptor.AllAssemblies.Returns(new List { moduleType.Assembly });
return moduleDescriptor;
}
}