advanced userinterface design

This commit is contained in:
Nitload
2026-04-01 22:20:49 +08:00
parent 24498c2717
commit aa7ece4ed0
42 changed files with 2876 additions and 463 deletions
@@ -0,0 +1,36 @@
using System;
using System.Threading;
using System.Threading.Tasks;
namespace StgSharp.UserInterface
{
public abstract class ServiceHost
{
protected ServiceHost(
string name
)
{
Name = string.IsNullOrWhiteSpace(name) ?
throw new ArgumentException("Value cannot be null or whitespace.", nameof(name)) :
name;
}
public string Name { get; }
public abstract Task<object?> ExecuteAsync(
ExecuteCommand command,
CancellationToken cancellationToken = default
);
public abstract ValueTask InitializeAsync(
ServiceLoadCommand command,
CancellationToken cancellationToken = default
);
public abstract ValueTask StopAsync(
CancellationToken cancellationToken = default
);
}
}
@@ -0,0 +1,15 @@
namespace StgSharp.UserInterface
{
public sealed record ServiceLoadAccomplishmentEvent
{
public string? Message { get; init; }
public ServiceHost? Host { get; init; }
public bool IsLoaded { get; init; }
public string ServiceName { get; init; } = string.Empty;
}
}
@@ -0,0 +1,24 @@
using System;
using System.Collections.Generic;
namespace StgSharp.UserInterface
{
public abstract record ServiceLoadCommand
{
protected ServiceLoadCommand(
string serviceName
)
{
ServiceName = string.IsNullOrWhiteSpace(serviceName) ?
throw new ArgumentException("Value cannot be null or whitespace.", nameof(serviceName)) :
serviceName;
}
public IReadOnlyDictionary<string, object?> Parameters { get; init; } =
new Dictionary<string, object?>(StringComparer.Ordinal);
public string ServiceName { get; init; }
}
}
@@ -0,0 +1,27 @@
using System;
using System.Collections.Generic;
namespace StgSharp.UserInterface
{
public abstract class AppState
{
protected AppState(
string name
)
{
Name = string.IsNullOrWhiteSpace(name) ?
throw new ArgumentException("Value cannot be null or whitespace.", nameof(name)) :
name;
}
public IDictionary<string, PanelState> Panels { get; } =
new Dictionary<string, PanelState>(StringComparer.Ordinal);
public IDictionary<string, object?> SharedContext { get; } =
new Dictionary<string, object?>(StringComparer.Ordinal);
public string Name { get; }
}
}
@@ -0,0 +1,32 @@
using System;
using System.Threading;
using System.Threading.Tasks;
namespace StgSharp.UserInterface
{
public abstract class FrontCommandHost
{
public StateHost StateHost { get; private set; } = null!;
public abstract Task<CommandResult> AcceptAsync(
ViewHost source,
StateChangeCommand command,
CancellationToken cancellationToken = default
);
public abstract Task<CommandResult> AcceptAsync(
ViewHost source,
ExecuteCommand command,
CancellationToken cancellationToken = default
);
internal void Attach(
StateHost stateHost
)
{
StateHost = stateHost ?? throw new ArgumentNullException(nameof(stateHost));
}
}
}
@@ -0,0 +1,63 @@
using System;
using System.Threading;
using System.Threading.Tasks;
namespace StgSharp.UserInterface
{
public abstract class StateHost
{
protected StateHost(
FrontCommandHost frontCommandHost,
AppState appState,
ServiceManager serviceManager
)
{
FrontCommandHost = frontCommandHost ??
throw new ArgumentNullException(nameof(frontCommandHost));
AppState = appState ?? throw new ArgumentNullException(nameof(appState));
ServiceManager = serviceManager ??
throw new ArgumentNullException(nameof(serviceManager));
FrontCommandHost.Attach(this);
ServiceManager.Attach(this);
}
public AppState AppState { get; }
public FrontCommandHost FrontCommandHost { get; }
public ServiceManager ServiceManager { get; }
public virtual async Task<CommandResult> PostAsync(
ViewHost source,
StateChangeCommand command,
CancellationToken cancellationToken = default
)
{
ArgumentNullException.ThrowIfNull(source);
ArgumentNullException.ThrowIfNull(command);
CommandResult result = await FrontCommandHost.AcceptAsync(source, command, cancellationToken)
.ConfigureAwait(false);
await source.ReceiveCommandResultAsync(result, cancellationToken).ConfigureAwait(false);
return result;
}
public virtual async Task<CommandResult> PostAsync(
ViewHost source,
ExecuteCommand command,
CancellationToken cancellationToken = default
)
{
ArgumentNullException.ThrowIfNull(source);
ArgumentNullException.ThrowIfNull(command);
CommandResult result = await FrontCommandHost.AcceptAsync(source, command, cancellationToken)
.ConfigureAwait(false);
await source.ReceiveCommandResultAsync(result, cancellationToken).ConfigureAwait(false);
return result;
}
}
}
@@ -0,0 +1,21 @@
using System;
using System.Collections.Generic;
namespace StgSharp.UserInterface
{
public abstract class PanelState
{
protected PanelState(
string name
)
{
Name = string.IsNullOrWhiteSpace(name) ?
throw new ArgumentException("Value cannot be null or whitespace.", nameof(name)) :
name;
}
public string Name { get; }
}
}
@@ -0,0 +1,36 @@
using System;
using System.Threading;
using System.Threading.Tasks;
namespace StgSharp.UserInterface
{
public abstract class ServiceManager
{
public StateHost StateHost { get; private set; } = null!;
public abstract Task<object?> ExecuteAsync(
ExecuteCommand command,
CancellationToken cancellationToken = default
);
public abstract Task<ServiceLoadAccomplishmentEvent> LoadAsync(
ServiceLoadCommand command,
CancellationToken cancellationToken = default
);
public abstract ValueTask RegisterAsync(
string serviceName,
ServiceHost serviceHost,
CancellationToken cancellationToken = default
);
internal void Attach(
StateHost stateHost
)
{
StateHost = stateHost ?? throw new ArgumentNullException(nameof(stateHost));
}
}
}
@@ -0,0 +1,21 @@
using System;
namespace StgSharp.UserInterface
{
public sealed record CommandResult
{
public string? Message { get; init; }
public object? Data { get; init; }
public bool IsSuccess { get; init; }
public bool IsRejected { get; init; }
public bool IsAborted { get; init; }
public Guid CommandId { get; init; }
}
}
@@ -0,0 +1,25 @@
using System;
using System.Collections.Generic;
namespace StgSharp.UserInterface
{
public abstract record ExecuteCommand
{
protected ExecuteCommand(
string operationName
)
{
OperationName = string.IsNullOrWhiteSpace(operationName) ?
throw new ArgumentException("Value cannot be null or whitespace.", nameof(operationName)) :
operationName;
}
public Guid CommandId { get; init; } = Guid.NewGuid();
public IReadOnlyList<object?> Parameters { get; init; } = Array.Empty<object?>();
public string OperationName { get; init; }
}
}
@@ -0,0 +1,53 @@
using System;
using System.Threading;
using System.Threading.Tasks;
namespace StgSharp.UserInterface
{
public abstract class ViewHost
{
protected ViewHost(
string name,
StateHost stateHost
)
{
Name = string.IsNullOrWhiteSpace(name) ?
throw new ArgumentException("Value cannot be null or whitespace.", nameof(name)) :
name;
StateHost = stateHost ?? throw new ArgumentNullException(nameof(stateHost));
}
public string Name { get; }
protected StateHost StateHost { get; }
public virtual Task<CommandResult> PostAsync(
StateChangeCommand command,
CancellationToken cancellationToken = default
)
{
ArgumentNullException.ThrowIfNull(command);
return StateHost.PostAsync(this, command, cancellationToken);
}
public virtual Task<CommandResult> PostAsync(
ExecuteCommand command,
CancellationToken cancellationToken = default
)
{
ArgumentNullException.ThrowIfNull(command);
return StateHost.PostAsync(this, command, cancellationToken);
}
public virtual ValueTask ReceiveCommandResultAsync(
CommandResult result,
CancellationToken cancellationToken = default
)
{
ArgumentNullException.ThrowIfNull(result);
return ValueTask.CompletedTask;
}
}
}
@@ -0,0 +1,24 @@
using System;
namespace StgSharp.UserInterface
{
public abstract record StateChangeCommand
{
protected StateChangeCommand(
string statePath
)
{
StatePath = string.IsNullOrWhiteSpace(statePath) ?
throw new ArgumentException("Value cannot be null or whitespace.", nameof(statePath)) :
statePath;
}
public object? Value { get; init; }
public Guid CommandId { get; init; } = Guid.NewGuid();
public string StatePath { get; init; }
}
}
@@ -0,0 +1,19 @@
using System;
namespace StgSharp.UserInterface
{
public sealed record StateValueCommand<TValue> : StateChangeCommand
{
public StateValueCommand(
string statePath,
TValue value
) : base(statePath)
{
Value = value;
}
public new TValue Value { get; init; }
}
}