This commit is contained in:
陈思海 2026-03-26 13:51:09 +08:00
parent 722dc7c251
commit 58baa6269e
3 changed files with 45 additions and 14 deletions

View File

@ -15,7 +15,34 @@ namespace AlicizaX
typeof(IServiceOrder),
};
// Cache for the common no-extraContracts path — contracts per concrete type never change.
private static readonly Dictionary<Type, List<Type>> _contractCache = new Dictionary<Type, List<Type>>();
public static List<Type> Collect(Type serviceType, IReadOnlyList<Type> extraContracts)
{
if (extraContracts == null || extraContracts.Count == 0)
{
if (_contractCache.TryGetValue(serviceType, out var cached))
return cached;
var result = BuildContracts(serviceType);
_contractCache[serviceType] = result;
return result;
}
// Extra contracts path: build fresh, validate, append extras.
var contracts = BuildContracts(serviceType);
contracts = new List<Type>(contracts); // don't mutate the cached list
var unique = new HashSet<Type>(contracts);
for (var i = 0; i < extraContracts.Count; i++)
{
var extraContract = extraContracts[i];
ValidateExtraContract(serviceType, extraContract);
if (unique.Add(extraContract)) contracts.Add(extraContract);
}
return contracts;
}
private static List<Type> BuildContracts(Type serviceType)
{
var contracts = new List<Type> { serviceType };
var unique = new HashSet<Type> { serviceType };
@ -28,16 +55,6 @@ namespace AlicizaX
if (ExcludedContracts.Contains(contract)) continue;
if (unique.Add(contract)) contracts.Add(contract);
}
if (extraContracts == null) return contracts;
for (var i = 0; i < extraContracts.Count; i++)
{
var extraContract = extraContracts[i];
ValidateExtraContract(serviceType, extraContract);
if (unique.Add(extraContract)) contracts.Add(extraContract);
}
return contracts;
}

View File

@ -154,10 +154,11 @@ namespace AlicizaX
var service = snapshot[i];
if (!_contractsByService.ContainsKey(service)) continue;
RemoveFromLifecycleLists(service);
RemoveBindings(service);
RemoveContractBindings(service); // skip _registrationOrder.Remove — we clear below
service.Destroy();
}
_registrationOrder.Clear();
IsDisposed = true;
}
@ -206,6 +207,17 @@ namespace AlicizaX
_registrationOrder.Remove(service);
}
// Used during full Dispose — skips the O(n) _registrationOrder.Remove since we clear the list afterwards.
private void RemoveContractBindings(IService service)
{
if (_contractsByService.TryGetValue(service, out var contracts))
{
for (var i = 0; i < contracts.Count; i++)
_servicesByContract.Remove(contracts[i]);
}
_contractsByService.Remove(service);
}
private IServiceTickable[] GetTickSnapshot()
{
if (_tickablesDirty)

View File

@ -61,9 +61,6 @@ namespace AlicizaX
// DefaultExecutionOrder 会影响所有生命周期(含 Awake用 Start 可彻底规避执行顺序陷阱。
private void Awake()
{
if (_dontDestroyOnLoad)
DontDestroyOnLoad(gameObject);
OnAwake();
}
@ -78,6 +75,11 @@ namespace AlicizaX
return;
}
// Defer DontDestroyOnLoad until after the duplicate check so rejected
// duplicates are never moved to the DontDestroyOnLoad scene.
if (_dontDestroyOnLoad)
DontDestroyOnLoad(gameObject);
scope.Register(this);
}