Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Abstract our request handler resolution #33

Draft
wants to merge 1 commit into
base: develop
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
43 changes: 43 additions & 0 deletions Source/Web.Maple.Server/AppDomainAssemblyRequestHandlerResolver.cs
Original file line number Diff line number Diff line change
@@ -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<Type>();

// 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();
}
}
8 changes: 8 additions & 0 deletions Source/Web.Maple.Server/IRequestHandlerResolver.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
using System;

namespace Meadow.Foundation.Web.Maple;

public interface IRequestHandlerResolver
{
Type[] Resolve();
}
46 changes: 26 additions & 20 deletions Source/Web.Maple.Server/MapleServer.cs
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,11 @@
/// </summary>
public RequestProcessMode ThreadingMode { get; protected set; }

/// <summary>
/// Resolver to find types which implement IRequestHandler.
/// </summary>
public IRequestHandlerResolver? RequestHandlerResolver { get; private set; }

/// <summary>
/// Whether or not the server should advertise it's name
/// and IP via UDP for discovery.
Expand Down Expand Up @@ -72,13 +77,14 @@
/// </summary>
public string DeviceName { get; set; } = "Meadow";

public MapleServer(

Check warning on line 80 in Source/Web.Maple.Server/MapleServer.cs

View workflow job for this annotation

GitHub Actions / build

Cannot convert null literal to non-nullable reference type.
string ipAddress,
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)
{
}

Expand All @@ -92,31 +98,38 @@
/// <param name="processMode">Whether or not the server should respond to
/// requests in parallel or serial. For Meadow, only Serial works
/// reliably today.</param>
/// <param name="logger">Logger to write output information to.</param>
/// <param name="requestHandlerResolver">Resolver for request handler types.
/// By default, the AppDomainAssemblyRequestHandlerResolver is used.</param>
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;

Advertise = advertise;
ThreadingMode = processMode;

RequestHandlerResolver = requestHandlerResolver;

if (IPAddress.Equals(IPAddress.Any))
{
// because .NET is apparently too stupid to understand "bind to all"
Expand Down Expand Up @@ -238,28 +251,21 @@
/// </summary>
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.");
Expand Down
Loading