refactor(app): define ordered composition contract
This commit is contained in:
parent
1d04b94da2
commit
adb204560d
6 changed files with 927 additions and 0 deletions
72
src/AcDream.App/Composition/GameWindowPlatformAcquisition.cs
Normal file
72
src/AcDream.App/Composition/GameWindowPlatformAcquisition.cs
Normal file
|
|
@ -0,0 +1,72 @@
|
|||
namespace AcDream.App.Composition;
|
||||
|
||||
internal interface IGameWindowPlatformPublication<in TGraphics, in TInput>
|
||||
where TGraphics : class
|
||||
where TInput : class
|
||||
{
|
||||
void PublishGraphics(TGraphics graphics);
|
||||
void PublishInput(TInput input);
|
||||
}
|
||||
|
||||
internal sealed record GameWindowPlatformResult<TGraphics, TInput>(
|
||||
TGraphics Graphics,
|
||||
TInput Input)
|
||||
where TGraphics : class
|
||||
where TInput : class;
|
||||
|
||||
internal enum GameWindowPlatformAcquisitionPoint
|
||||
{
|
||||
GraphicsPublished,
|
||||
InputPublished,
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Exact host-platform acquisition prelude. Graphics ownership publishes
|
||||
/// before input construction starts so a later input failure remains
|
||||
/// recoverable through the normal lifetime transaction.
|
||||
/// </summary>
|
||||
internal static class GameWindowPlatformAcquisition
|
||||
{
|
||||
public static GameWindowPlatformResult<TGraphics, TInput> Acquire<TGraphics, TInput>(
|
||||
Func<TGraphics> graphicsFactory,
|
||||
Action<TGraphics> releaseUnpublishedGraphics,
|
||||
Func<TInput> inputFactory,
|
||||
Action<TInput> releaseUnpublishedInput,
|
||||
IGameWindowPlatformPublication<TGraphics, TInput> publication,
|
||||
Action<GameWindowPlatformAcquisitionPoint>? faultInjection = null)
|
||||
where TGraphics : class
|
||||
where TInput : class
|
||||
{
|
||||
ArgumentNullException.ThrowIfNull(graphicsFactory);
|
||||
ArgumentNullException.ThrowIfNull(releaseUnpublishedGraphics);
|
||||
ArgumentNullException.ThrowIfNull(inputFactory);
|
||||
ArgumentNullException.ThrowIfNull(releaseUnpublishedInput);
|
||||
ArgumentNullException.ThrowIfNull(publication);
|
||||
|
||||
var scope = new CompositionAcquisitionScope();
|
||||
try
|
||||
{
|
||||
var graphicsLease = scope.Acquire(
|
||||
"graphics API",
|
||||
graphicsFactory,
|
||||
releaseUnpublishedGraphics);
|
||||
TGraphics graphics = graphicsLease.Publish(publication.PublishGraphics);
|
||||
faultInjection?.Invoke(GameWindowPlatformAcquisitionPoint.GraphicsPublished);
|
||||
|
||||
var inputLease = scope.Acquire(
|
||||
"input context",
|
||||
inputFactory,
|
||||
releaseUnpublishedInput);
|
||||
TInput input = inputLease.Publish(publication.PublishInput);
|
||||
faultInjection?.Invoke(GameWindowPlatformAcquisitionPoint.InputPublished);
|
||||
|
||||
scope.Complete();
|
||||
return new GameWindowPlatformResult<TGraphics, TInput>(graphics, input);
|
||||
}
|
||||
catch (Exception failure)
|
||||
{
|
||||
scope.RollbackAndThrow(failure);
|
||||
throw new System.Diagnostics.UnreachableException();
|
||||
}
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue