Registry and runner for architecture affectors. Defines IArchAffector interface and ArchAffectors table that holds available affector implementations, orders them, runs Resolve on each to modify an ArchPlan using an ArchKit, and invokes Close on affectors matching a payload. Also tidies empty assemblies after running.
namespace Sunless.Architecture;
public interface IArchAffector
{
ArchKind Kind { get; }
int Order { get; }
int Resolve( ArchPlan plan, ArchKit kit );
bool Closes( object payload );
void Close( ArchPlan plan, object payload );
}
public sealed class ArchAffectors : ArchTable<ArchAffectors, ArchKind, IArchAffector>
{
protected override IEnumerable<IArchAffector> Standing()
{
yield return new ArchCutEffects();
yield return new ArchTrimEffects();
yield return new ArchOpeningRunEffects();
yield return new ArchBalconyEffects();
yield return new ArchStairEffects();
yield return new ArchExteriorStairEffects();
yield return new ArchPorchEffects();
yield return new ArchWalkwayAffector();
}
protected override ArchKind KeyOf( IArchAffector affector ) => affector.Kind;
protected override bool Accepts( IArchAffector affector ) => affector.Kind.Known;
protected override string Collision( IArchAffector standing, IArchAffector affector )
{
return $"{affector.Kind.Ident} affector is claimed by both {standing.GetType().Name} and {affector.GetType().Name}";
}
public IArchAffector For( ArchKind kind ) => Held( kind );
public IReadOnlyList<IArchAffector> Ordered => Entries
.OrderBy( affector => affector.Order )
.ThenBy( affector => affector.Kind.Ident, StringComparer.Ordinal )
.ToList();
public int Run( ArchPlan plan, ArchKit kit )
{
var resolved = Ordered.Sum( affector => affector.Resolve( plan, kit ) );
Tidy( plan );
return resolved;
}
public void CloseMatching( ArchPlan plan, object payload )
{
if ( plan is null || payload is null )
{
return;
}
foreach ( var affector in Ordered.Where( candidate => candidate.Closes( payload ) ) )
{
affector.Close( plan, payload );
}
}
public static int Resolve( ArchPlan plan, ArchKit kit ) => Load().Run( plan, kit );
public static void Close( ArchPlan plan, object payload ) => Load().CloseMatching( plan, payload );
static void Tidy( ArchPlan plan )
{
foreach ( var empty in plan.Assemblies.Where( group => group.Children.Count == 0 ).ToList() )
{
ArchLayerGroups.Dissolve( plan, empty );
}
}
}