This commit is contained in:
@@ -0,0 +1,154 @@
|
||||
#nullable enable
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace ShrinkContext
|
||||
{
|
||||
/// <summary>共享存储中的一条依赖绑定:键解析到 realm 后对应的值与提供者纤程。</summary>
|
||||
public sealed class ShrinkBinding
|
||||
{
|
||||
public ShrinkBinding(object? value, ShrinkFiber? provider, string key,
|
||||
IShrinkCoeffectAccessPolicy? accessPolicy = null)
|
||||
{
|
||||
Value = value;
|
||||
Provider = provider;
|
||||
Key = key;
|
||||
AccessPolicy = accessPolicy;
|
||||
}
|
||||
|
||||
public object? Value { get; }
|
||||
public ShrinkFiber? Provider { get; }
|
||||
public string Key { get; }
|
||||
public IShrinkCoeffectAccessPolicy? AccessPolicy { get; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 带命名空间与主版本的类型化余效应键。现有字符串声明可继续使用 <see cref="Id"/>,
|
||||
/// Set/Get 重载则在调用点固定值类型,逐步收口字符串键的碰撞与接口漂移。
|
||||
/// </summary>
|
||||
public sealed class ShrinkKey<T>
|
||||
{
|
||||
public ShrinkKey(string packageName, string name, int majorVersion = 1)
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(packageName))
|
||||
throw new ArgumentException("Package name must not be empty.", nameof(packageName));
|
||||
if (string.IsNullOrWhiteSpace(name))
|
||||
throw new ArgumentException("Key name must not be empty.", nameof(name));
|
||||
if (majorVersion <= 0)
|
||||
throw new ArgumentOutOfRangeException(nameof(majorVersion), "Major version must be positive.");
|
||||
|
||||
PackageName = packageName.Trim();
|
||||
Name = name.Trim();
|
||||
MajorVersion = majorVersion;
|
||||
Id = $"{PackageName}/{Name}@v{MajorVersion}";
|
||||
}
|
||||
|
||||
public string PackageName { get; }
|
||||
public string Name { get; }
|
||||
public int MajorVersion { get; }
|
||||
public string Id { get; }
|
||||
public override string ToString() => Id;
|
||||
}
|
||||
|
||||
/// <summary>依赖值被读取时的访问上下文;metadata 来自访问方上下文上的 intercept 合并结果。</summary>
|
||||
public sealed class ShrinkCoeffectAccessContext
|
||||
{
|
||||
internal ShrinkCoeffectAccessContext(string key, Type requestedType, ShrinkFiber? consumer,
|
||||
IReadOnlyDictionary<string, object?> metadata)
|
||||
{
|
||||
Key = key;
|
||||
RequestedType = requestedType;
|
||||
Consumer = consumer;
|
||||
Metadata = metadata;
|
||||
}
|
||||
|
||||
public string Key { get; }
|
||||
public Type RequestedType { get; }
|
||||
public ShrinkFiber? Consumer { get; }
|
||||
public IReadOnlyDictionary<string, object?> Metadata { get; }
|
||||
|
||||
public bool TryGetMetadata<T>(string name, out T value)
|
||||
{
|
||||
if (Metadata.TryGetValue(name, out var raw) && raw is T typed)
|
||||
{
|
||||
value = typed;
|
||||
return true;
|
||||
}
|
||||
|
||||
value = default!;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// provider 侧访问策略。它可以依据 intercept metadata 返回降权包装或拒绝访问,
|
||||
/// 但不会改变依赖满足关系,也不会构成不可信代码沙箱。
|
||||
/// </summary>
|
||||
public interface IShrinkCoeffectAccessPolicy
|
||||
{
|
||||
object? Resolve(ShrinkCoeffectAccessContext context, object? value);
|
||||
}
|
||||
|
||||
/// <summary>访问了纤程链上没有任何一方声明的依赖键(论文算法 6 的 UNDECLARED_ACCESS)。</summary>
|
||||
public sealed class ShrinkUndeclaredAccessException : Exception
|
||||
{
|
||||
public ShrinkUndeclaredAccessException(string key)
|
||||
: base($"Undeclared coeffect access: '{key}'. Declare it in the component's Inject list.")
|
||||
{
|
||||
Key = key;
|
||||
}
|
||||
|
||||
public string Key { get; }
|
||||
}
|
||||
|
||||
/// <summary>纤程声明了依赖键但尚未激活就访问(论文算法 6 的 INACTIVE_ACCESS)。</summary>
|
||||
public sealed class ShrinkInactiveAccessException : Exception
|
||||
{
|
||||
public ShrinkInactiveAccessException(string key, string fiberName)
|
||||
: base($"Inactive coeffect access: '{key}' declared by fiber '{fiberName}' but not committed yet.")
|
||||
{
|
||||
Key = key;
|
||||
}
|
||||
|
||||
public string Key { get; }
|
||||
}
|
||||
|
||||
/// <summary>组件写入了未在 Provide 中声明的键。</summary>
|
||||
public sealed class ShrinkUndeclaredSupplyException : Exception
|
||||
{
|
||||
public ShrinkUndeclaredSupplyException(string key, string fiberName)
|
||||
: base($"Undeclared coeffect supply: '{key}' is not listed in fiber '{fiberName}' Provide keys.")
|
||||
{
|
||||
Key = key;
|
||||
FiberName = fiberName;
|
||||
}
|
||||
|
||||
public string Key { get; }
|
||||
public string FiberName { get; }
|
||||
}
|
||||
|
||||
/// <summary>intercept 访问策略拒绝了本次依赖读取。</summary>
|
||||
public sealed class ShrinkCoeffectAccessDeniedException : Exception
|
||||
{
|
||||
public ShrinkCoeffectAccessDeniedException(string key, string message)
|
||||
: base($"Coeffect access denied for '{key}': {message}")
|
||||
{
|
||||
Key = key;
|
||||
}
|
||||
|
||||
public string Key { get; }
|
||||
}
|
||||
|
||||
/// <summary>两个活跃纤程试图供给同一个 realm(论文定义 45 的供给不相交约束)。</summary>
|
||||
public sealed class ShrinkSupplyConflictException : Exception
|
||||
{
|
||||
public ShrinkSupplyConflictException(string key, ShrinkFiber? existing, ShrinkFiber? setter)
|
||||
: base($"Supply conflict on key '{key}': existing provider " +
|
||||
$"'{existing?.Name ?? "<ambient>"}' conflicts with '{setter?.Name ?? "<ambient>"}'.")
|
||||
{
|
||||
Key = key;
|
||||
}
|
||||
|
||||
public string Key { get; }
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 2dcad9bdadb1607498dc233cfc1b5a06
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
Reference in New Issue
Block a user