diff --git a/src/Testing/CoreTests/Configuration/find_handlers_with_the_default_handler_discovery.cs b/src/Testing/CoreTests/Configuration/find_handlers_with_the_default_handler_discovery.cs index 1158359ca..953d0c529 100644 --- a/src/Testing/CoreTests/Configuration/find_handlers_with_the_default_handler_discovery.cs +++ b/src/Testing/CoreTests/Configuration/find_handlers_with_the_default_handler_discovery.cs @@ -176,6 +176,20 @@ public void find_handlers_from_included_assembly() chainFor().ShouldNotBeNull(); chainFor().ShouldNotBeNull(); } + + [Fact] + public void find_handlers_from_handler_module_assemblies() + { + with(opts => + { + opts.Discovery.IncludeHandlerModules = true; + }); + + chainFor().ShouldNotBeNull(); + chainFor().ShouldNotBeNull(); + chainFor().ShouldNotBeNull(); + chainFor().ShouldNotBeNull(); + } } public interface IMovieSink @@ -283,4 +297,4 @@ public class EventConsumer public void Consume(Event1 @event) { } -} \ No newline at end of file +} diff --git a/src/Testing/Module2/Module2.csproj b/src/Testing/Module2/Module2.csproj index 61718a1f8..32dcdcedb 100644 --- a/src/Testing/Module2/Module2.csproj +++ b/src/Testing/Module2/Module2.csproj @@ -1,3 +1,5 @@ - + + + diff --git a/src/Testing/Module2/Properties/AssemblyInfo.cs b/src/Testing/Module2/Properties/AssemblyInfo.cs new file mode 100644 index 000000000..07c9396f6 --- /dev/null +++ b/src/Testing/Module2/Properties/AssemblyInfo.cs @@ -0,0 +1,3 @@ +using Wolverine.Attributes; + +[assembly: WolverineHandlerModule] diff --git a/src/Wolverine/Attributes/WolverineHandlerModuleAttribute.cs b/src/Wolverine/Attributes/WolverineHandlerModuleAttribute.cs new file mode 100644 index 000000000..77f1cf40b --- /dev/null +++ b/src/Wolverine/Attributes/WolverineHandlerModuleAttribute.cs @@ -0,0 +1,10 @@ +using JasperFx; + +namespace Wolverine.Attributes; + +/// +/// Assembly-level marker attribute that designates an assembly +/// as containing Wolverine message handlers for automatic discovery. +/// +[AttributeUsage(AttributeTargets.Assembly)] +public class WolverineHandlerModuleAttribute : JasperFxAssemblyAttribute; diff --git a/src/Wolverine/Configuration/HandlerDiscovery.cs b/src/Wolverine/Configuration/HandlerDiscovery.cs index 5dddf30db..9afa723ca 100644 --- a/src/Wolverine/Configuration/HandlerDiscovery.cs +++ b/src/Wolverine/Configuration/HandlerDiscovery.cs @@ -104,6 +104,11 @@ private static bool isNotPublicType(Type type) return true; } + /// + /// + /// + public bool IncludeHandlerModules { get; set; } = false; + /// /// Customize the conventional filtering on the handler type discovery. This is *additive* to the /// built in conventional handler discovery. Disabling conventional discovery will negate anything @@ -181,6 +186,22 @@ internal IEnumerable findAllMessages(HandlerGraph handlers) .Distinct() .SelectMany(actionsFromType).ToArray(); } + + /// + /// Discovers and includes all assemblies marked with [WolverineHandlerModule] attribute. + /// + internal HandlerDiscovery DiscoverHandlerModules() + { + var handlerModuleAssemblies = AssemblyFinder + .FindAssemblies(a => a.HasAttribute()) + .Concat(AppDomain.CurrentDomain.GetAssemblies()) + .Distinct() + .Where(a => a.HasAttribute()) + .ToArray(); + + Assemblies.AddRange(handlerModuleAssemblies); + return this; + } private IEnumerable<(Type, MethodInfo)> actionsFromType(Type type) { diff --git a/src/Wolverine/HostBuilderExtensions.cs b/src/Wolverine/HostBuilderExtensions.cs index 5bff37a64..294b8c86e 100644 --- a/src/Wolverine/HostBuilderExtensions.cs +++ b/src/Wolverine/HostBuilderExtensions.cs @@ -225,6 +225,11 @@ internal static IServiceCollection AddWolverine(this IServiceCollection services configure?.Invoke(options); + if (options.Discovery.IncludeHandlerModules) + { + options.HandlerGraph.Discovery.DiscoverHandlerModules(); + } + options.ApplyLazyConfiguration(); return services; @@ -476,4 +481,4 @@ public void Configure(WolverineOptions options) options.Durability.Mode = DurabilityMode.Solo; } } -} \ No newline at end of file +}