diff --git a/Source/Web.Maple.Server/AppDomainAssemblyRequestHandlerResolver.cs b/Source/Web.Maple.Server/AppDomainAssemblyRequestHandlerResolver.cs new file mode 100644 index 0000000..bf088d5 --- /dev/null +++ b/Source/Web.Maple.Server/AppDomainAssemblyRequestHandlerResolver.cs @@ -0,0 +1,43 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using Meadow.Logging; + +namespace Meadow.Foundation.Web.Maple; + +public class AppDomainAssemblyRequestHandlerResolver : IRequestHandlerResolver +{ + public AppDomainAssemblyRequestHandlerResolver(Logger? logger) + { + Logger = logger; + } + + readonly Logger? Logger; + + public Type[] Resolve() + { + var resolved = new List(); + + // Get classes that implement IRequestHandler + var assemblies = AppDomain.CurrentDomain.GetAssemblies(); + + // loop through each assembly in the app and all the classes in it + foreach (var assembly in assemblies) + { + var types = assembly.GetTypes(); + foreach (var t in types) + { + // if it inherits `IRequestHandler`, add it to the list + if (t.BaseType != null) + { + if (t.BaseType.GetInterfaces().Contains(typeof(IRequestHandler))) + { + resolved.Add(t); + } + } + } + } + + return resolved.ToArray(); + } +} \ No newline at end of file diff --git a/Source/Web.Maple.Server/IRequestHandlerResolver.cs b/Source/Web.Maple.Server/IRequestHandlerResolver.cs new file mode 100644 index 0000000..1b3e679 --- /dev/null +++ b/Source/Web.Maple.Server/IRequestHandlerResolver.cs @@ -0,0 +1,8 @@ +using System; + +namespace Meadow.Foundation.Web.Maple; + +public interface IRequestHandlerResolver +{ + Type[] Resolve(); +} \ No newline at end of file diff --git a/Source/Web.Maple.Server/MapleServer.cs b/Source/Web.Maple.Server/MapleServer.cs index f41c8d0..6892f61 100644 --- a/Source/Web.Maple.Server/MapleServer.cs +++ b/Source/Web.Maple.Server/MapleServer.cs @@ -44,6 +44,11 @@ public partial class MapleServer /// public RequestProcessMode ThreadingMode { get; protected set; } + /// + /// Resolver to find types which implement IRequestHandler. + /// + public IRequestHandlerResolver? RequestHandlerResolver { get; private set; } + /// /// Whether or not the server should advertise it's name /// and IP via UDP for discovery. @@ -77,8 +82,9 @@ public MapleServer( int port = DefaultPort, bool advertise = false, RequestProcessMode processMode = RequestProcessMode.Serial, - Logger logger = null) - : this(IPAddress.Parse(ipAddress), port, advertise, processMode, logger) + Logger? logger = null, + IRequestHandlerResolver? requestHandlerResolver = null) + : this(IPAddress.Parse(ipAddress), port, advertise, processMode, logger, requestHandlerResolver) { } @@ -92,24 +98,29 @@ public MapleServer( /// Whether or not the server should respond to /// requests in parallel or serial. For Meadow, only Serial works /// reliably today. + /// Logger to write output information to. + /// Resolver for request handler types. + /// By default, the AppDomainAssemblyRequestHandlerResolver is used. public MapleServer( IPAddress ipAddress, int port = DefaultPort, bool advertise = false, RequestProcessMode processMode = RequestProcessMode.Serial, - Logger? logger = null) + Logger? logger = null, + IRequestHandlerResolver? requestHandlerResolver = null) { Logger = logger; MethodCache = new RequestMethodCache(Logger); ErrorPageGenerator = new ErrorPageGenerator(); - Create(ipAddress, port, advertise, processMode); + Create(ipAddress, port, advertise, processMode, requestHandlerResolver); } private void Create(IPAddress ipAddress, int port, bool advertise, - RequestProcessMode processMode) + RequestProcessMode processMode, + IRequestHandlerResolver? requestHandlerResolver = null) { IPAddress = ipAddress ?? throw new ArgumentNullException(nameof(ipAddress)); Port = port; @@ -117,6 +128,8 @@ private void Create(IPAddress ipAddress, Advertise = advertise; ThreadingMode = processMode; + RequestHandlerResolver = requestHandlerResolver; + if (IPAddress.Equals(IPAddress.Any)) { // because .NET is apparently too stupid to understand "bind to all" @@ -238,28 +251,21 @@ protected void StartUdpAdvertisement() /// protected void LoadRequestHandlers() { - // Get classes that implement IRequestHandler - var assemblies = AppDomain.CurrentDomain.GetAssemblies(); + var resolver = RequestHandlerResolver ?? new AppDomainAssemblyRequestHandlerResolver(Logger); var typesAdded = 0; - - // loop through each assembly in the app and all the classes in it - foreach (var assembly in assemblies) + var resolvedTypes = resolver.Resolve(); + foreach (var resolvedType in resolvedTypes) { - var types = assembly.GetTypes(); - foreach (var t in types) + if (resolvedType.BaseType != null) { - // if it inherits `IRequestHandler`, add it to the list - if (t.BaseType != null) + if (resolvedType.BaseType.GetInterfaces().Contains(typeof(IRequestHandler))) { - if (t.BaseType.GetInterfaces().Contains(typeof(IRequestHandler))) - { - MethodCache.AddType(t); - typesAdded++; - } + MethodCache.AddType(resolvedType); + typesAdded++; } } } - + if (typesAdded == 0) { Console.WriteLine("Warning: No Maple Server `IRequestHandler`s found. Server will not operate.");