Skip to content
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
75 changes: 75 additions & 0 deletions FrigidRogue.MonoGame.Core.Tests/Components/MediatorTests.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
using FrigidRogue.MonoGame.Core.Components.Mediator;
using Microsoft.VisualStudio.TestTools.UnitTesting;

namespace FrigidRogue.MonoGame.Core.Tests.Components
{
[TestClass]
public class MediatorTests
{
[TestMethod]
public void Send_Should_Call_Request_Handler()
{
// Arrange
var handler = new TestRequestHandler();
var mediator = new Mediator(type =>
type == typeof(IRequestHandler<TestRequest>)
? handler
: throw new InvalidOperationException());

// Act
mediator.Send(new TestRequest());

// Assert
Assert.AreEqual(1, handler.HandleCount);
}

[TestMethod]
public void Publish_Should_Call_All_Notification_Handlers()
{
// Arrange
var firstHandler = new TestNotificationHandler();
var secondHandler = new TestNotificationHandler();
var handlers = new INotificationHandler<TestNotification>[] { firstHandler, secondHandler };

var mediator = new Mediator(type =>
type == typeof(IEnumerable<INotificationHandler<TestNotification>>)
? handlers
: throw new InvalidOperationException());

// Act
mediator.Publish(new TestNotification());

// Assert
Assert.AreEqual(1, firstHandler.HandleCount);
Assert.AreEqual(1, secondHandler.HandleCount);
}

private class TestRequest : IRequest
{
}

private class TestNotification : INotification
{
}

private class TestRequestHandler : IRequestHandler<TestRequest>
{
public int HandleCount { get; private set; }

public void Handle(TestRequest request)
{
HandleCount++;
}
}

private class TestNotificationHandler : INotificationHandler<TestNotification>
{
public int HandleCount { get; private set; }

public void Handle(TestNotification request)
{
HandleCount++;
}
}
}
}
Original file line number Diff line number Diff line change
@@ -1,8 +1,6 @@
using System.ComponentModel.Design;

using Castle.Core;

using FrigidRogue.MonoGame.Core.Interfaces.Components;
using FrigidRogue.MonoGame.Core.Interfaces.Components;
using FrigidRogue.MonoGame.Core.Services;

using GoRogue.Random;
Expand Down Expand Up @@ -233,4 +231,4 @@ public virtual int NextInt(int lower, int upper, string context)
return NextInt(lower, upper);
}
}
}
}
70 changes: 27 additions & 43 deletions FrigidRogue.MonoGame.Core/Components/Mediator/Mediator.cs
Original file line number Diff line number Diff line change
@@ -1,43 +1,27 @@
using Castle.MicroKernel;

namespace FrigidRogue.MonoGame.Core.Components.Mediator;

public class Mediator : IMediator
{
// property-injected
public IKernel Kernel { get; set; }

public Mediator()
{
}

public void Publish<T>(T notification) where T : INotification
{
var instances = Kernel.Resolve<ServiceFactory>().GetInstances<INotificationHandler<T>>();

try
{
foreach (var instance in instances)
instance.Handle(notification);
}
finally
{
foreach (var instance in instances)
Kernel.ReleaseComponent(instance);
}
}

public void Send<T>(T request) where T : IRequest
{
var instance = Kernel.Resolve<ServiceFactory>().GetInstance<IRequestHandler<T>>();

try
{
instance.Handle(request);
}
finally
{
Kernel.ReleaseComponent(instance);
}
}
}
namespace FrigidRogue.MonoGame.Core.Components.Mediator;

public class Mediator : IMediator
{
private readonly ServiceFactory _serviceFactory;

public Mediator(ServiceFactory serviceFactory)
{
_serviceFactory = serviceFactory;
}

public void Publish<T>(T notification) where T : INotification
{
var instances = _serviceFactory.GetInstances<INotificationHandler<T>>();

foreach (var instance in instances)
{
instance.Handle(notification);
}
}

public void Send<T>(T request) where T : IRequest
{
var instance = _serviceFactory.GetInstance<IRequestHandler<T>>();
instance.Handle(request);
}
}
Original file line number Diff line number Diff line change
@@ -1,17 +1,17 @@
using Castle.Core.Internal;
using FrigidRogue.MonoGame.Core.Interfaces.ConsoleCommands;
using System.Reflection;
using FrigidRogue.MonoGame.Core.Interfaces.ConsoleCommands;

namespace FrigidRogue.MonoGame.Core.ConsoleCommands
{
public class ConsoleCommandServiceFactory : IConsoleCommandServiceFactory
{
private readonly Dictionary<string, IConsoleCommand> _consoleCommands;

public ConsoleCommandServiceFactory(IConsoleCommand[] consoleCommands)
{
_consoleCommands = consoleCommands
.ToDictionary(c => c.GetType().GetAttributes<ConsoleCommandAttribute>().Single().Name.ToLower());
}
public ConsoleCommandServiceFactory(IEnumerable<IConsoleCommand> consoleCommands)
{
_consoleCommands = consoleCommands
.ToDictionary(c => c.GetType().GetCustomAttributes<ConsoleCommandAttribute>().Single().Name.ToLower());
}

public IConsoleCommand CommandFor(ConsoleCommand command)
{
Expand Down
9 changes: 4 additions & 5 deletions FrigidRogue.MonoGame.Core/FrigidRogue.MonoGame.Core.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,10 @@
<TargetFramework>net8.0-windows</TargetFramework>
</PropertyGroup>

<ItemGroup>
<PackageReference Include="Castle.Core" Version="5.1.1" />
<PackageReference Include="Castle.Windsor" Version="6.0.0" />
<PackageReference Include="InputHandlers.MonoGame.WindowsDX" Version="1.9.0" />
<PackageReference Include="MonoGame.Framework.WindowsDX" Version="3.8.3" />
<ItemGroup>
<PackageReference Include="InputHandlers.MonoGame.WindowsDX" Version="1.9.0" />
<PackageReference Include="Microsoft.Extensions.DependencyInjection" Version="9.0.1" />
<PackageReference Include="MonoGame.Framework.WindowsDX" Version="3.8.3" />
<PackageReference Include="Newtonsoft.Json" Version="13.0.3" />
<PackageReference Include="NGenerics" Version="1.5.3" />
<PackageReference Include="Serilog" Version="4.2.0" />
Expand Down
160 changes: 53 additions & 107 deletions FrigidRogue.MonoGame.Core/Installers/CoreInstaller.cs
Original file line number Diff line number Diff line change
@@ -1,12 +1,7 @@
using System.Reflection;
using Castle.Facilities.TypedFactory;
using Castle.MicroKernel.Registration;
using Castle.MicroKernel.Resolvers.SpecializedResolvers;
using Castle.MicroKernel.SubSystems.Configuration;
using Castle.Windsor;
using FrigidRogue.MonoGame.Core.Components;
using FrigidRogue.MonoGame.Core.Configuration;
using FrigidRogue.MonoGame.Core.ConsoleCommands;
using System.Reflection;
using FrigidRogue.MonoGame.Core.Components;
using FrigidRogue.MonoGame.Core.Configuration;
using FrigidRogue.MonoGame.Core.ConsoleCommands;
using FrigidRogue.MonoGame.Core.Graphics;
using FrigidRogue.MonoGame.Core.Graphics.Quads;
using FrigidRogue.MonoGame.Core.Interfaces.Components;
Expand All @@ -16,110 +11,61 @@
using FrigidRogue.MonoGame.Core.Interfaces.UserInterface;
using FrigidRogue.MonoGame.Core.Services;
using FrigidRogue.MonoGame.Core.UserInterface;
using InputHandlers.Keyboard;
using InputHandlers.Mouse;
using Microsoft.Extensions.Configuration;
using Serilog;
using Serilog.Core;
using InputHandlers.Keyboard;
using InputHandlers.Mouse;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.DependencyInjection.Extensions;
using Serilog;
using Serilog.Core;

namespace FrigidRogue.MonoGame.Core.Installers
{
public class CoreInstaller : IWindsorInstaller
{
public void Install(IWindsorContainer container, IConfigurationStore store)
{
Logger loggerConfig;

if (container.Kernel.HasComponent(typeof(IConfiguration)))
{
var configuration = container.Resolve<IConfiguration>();

loggerConfig = new LoggerConfiguration()
.ReadFrom.Configuration(configuration)
.CreateLogger();
public class CoreInstaller
{
public void Install(IServiceCollection services, IConfiguration configuration = null)
{
Logger loggerConfig;

if (configuration != null)
{
loggerConfig = new LoggerConfiguration()
.ReadFrom.Configuration(configuration)
.CreateLogger();
}
else
{
loggerConfig = new LoggerConfiguration()
.WriteTo.File($"{Assembly.GetEntryAssembly()?.GetName().Name ?? "Game"}.log")
.MinimumLevel.Debug()
.CreateLogger();
}

container.AddFacility<TypedFactoryFacility>();

container.Kernel.Resolver.AddSubResolver(new CollectionResolver(container.Kernel, true));

container.Kernel.ComponentModelBuilder.AddContributor(new RequestHandlerContributor());
container.Kernel.ComponentModelBuilder.AddContributor(new NotificationHandlerContributor());

container.Install(new MediatorInstaller());

container.Register(

Component.For<ILogger>()
.Instance(loggerConfig),

Component.For<IGameTimeService>()
.ImplementedBy<GameTimeService>(),

Component.For<IGameTurnService>()
.ImplementedBy<GameTurnService>(),

Component.For<ISaveGameService>()
.ImplementedBy<SaveGameService>(),

Component.For<ISaveGameFileWriter>()
.ImplementedBy<SaveGameFileWriter>(),

Component.For<IGameInputService>()
.ImplementedBy<GameInputService>(),

Component.For<IStopwatchProvider>()
.ImplementedBy<StopwatchProvider>()
.LifeStyle.Transient,

Component.For<IKeyboardInput>()
.ImplementedBy<KeyboardInput>(),

Component.For<IMouseInput>()
.ImplementedBy<MouseInput>(),

Component.For<IDateTimeProvider>()
.ImplementedBy<DateTimeProvider>(),

Component.For<IGameProvider>()
.ImplementedBy<GameProvider>(),

Component.For<IGameOptionsStore>()
.ImplementedBy<GameOptionsStore>(),

Component.For<MaterialQuadTemplate>()
.LifeStyle.Transient,

Component.For<TexturedQuadTemplate>()
.LifeStyle.Transient,

Component.For<IConfigurationSettings>()
.ImplementedBy<ConfigurationSettings>(),

Component.For<IConsoleCommandServiceFactory>()
.ImplementedBy<ConsoleCommandServiceFactory>(),

Component.For<IGraphicsSettings>()
.UsingFactoryMethod(k => BaseConfigurationSectionHandler.Load<GraphicsSettings>()),

Component.For<IActionMap>()
.ImplementedBy<ActionMap>(),

Component.For<IActionMapStore>()
.ImplementedBy<EmptyActionMapStore>()
.IsFallback(),

Component.For<ISceneGraph>()
.ImplementedBy<SceneGraph>()
.LifeStyle.Transient
);
}
}
}
.CreateLogger();
}

new RequestHandlerContributor().Process(services, typeof(CoreInstaller).Assembly);
new NotificationHandlerContributor().Process(services, typeof(CoreInstaller).Assembly);

new MediatorInstaller().Install(services);

services.AddSingleton<ILogger>(loggerConfig);
services.AddTransient<IGameTimeService, GameTimeService>();
services.AddTransient<IGameTurnService, GameTurnService>();
services.AddTransient<ISaveGameService, SaveGameService>();
services.AddTransient<ISaveGameFileWriter, SaveGameFileWriter>();
services.AddTransient<IGameInputService, GameInputService>();
services.AddTransient<IStopwatchProvider, StopwatchProvider>();
services.AddTransient<IKeyboardInput, KeyboardInput>();
services.AddTransient<IMouseInput, MouseInput>();
services.AddTransient<IDateTimeProvider, DateTimeProvider>();
services.AddTransient<IGameProvider, GameProvider>();
services.AddTransient<IGameOptionsStore, GameOptionsStore>();
services.AddTransient<MaterialQuadTemplate>();
services.AddTransient<TexturedQuadTemplate>();
services.AddTransient<IConfigurationSettings, ConfigurationSettings>();
services.AddTransient<IConsoleCommandServiceFactory, ConsoleCommandServiceFactory>();
services.AddTransient<IGraphicsSettings>(_ => BaseConfigurationSectionHandler.Load<GraphicsSettings>());
services.AddTransient<IActionMap, ActionMap>();
services.TryAddTransient<IActionMapStore, EmptyActionMapStore>();
services.AddTransient<ISceneGraph, SceneGraph>();
}
}
}
Loading