| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119 |
- using System;
- using System.Collections.Generic;
- namespace TeamAAS.Global
- {
- /// <summary>
- /// 插件运行上下文:插件获取平台服务的唯一正规渠道。
- /// 目标:插件代码不再直接摸 CameraManager.Instance 等静态单例,
- /// 而是向宿主要服务 —— 宿主可以把服务放在本进程、独立进程甚至远端(分布式扩展点)。
- /// 阶段1:接口先行,宿主适配器后续接入;现有插件行为不受影响。
- /// </summary>
- public interface IPluginContext
- {
- /// <summary>按类型获取平台服务(相机/机器人/通讯/供料/运动卡管理器等)。未注册返回 null。</summary>
- T GetService<T>();
- /// <summary>按类型对象获取平台服务(非泛型版,供反射场景)。未注册返回 null。</summary>
- object GetService(Type serviceType);
- /// <summary>按类型与名称获取设备(如相机名、通讯设备名)。找不到返回 null。</summary>
- T GetDevice<T>(string deviceName);
- /// <summary>获取某类设备的全部实例。</summary>
- IEnumerable<T> GetDevices<T>();
- /// <summary>写一条插件日志(level 1~4 详细度,语义与 BasePlugin.Log 一致)。</summary>
- void Log(string flowName, string nodeName, int level, string message, string category = "Info");
- }
- /// <summary>
- /// 简单服务注册表:宿主启动时注册实例,插件经由 IPluginContext 消费。
- /// 线程安全;第一阶段由主程序把现有 Manager 单例注册进来(Adapter 模式,零行为变化)。
- /// </summary>
- public sealed class ServiceRegistry : IPluginContext
- {
- private static readonly Lazy<ServiceRegistry> _default =
- new Lazy<ServiceRegistry>(() => new ServiceRegistry(), isThreadSafe: true);
- /// <summary>全局默认注册表(宿主未注入自定义实现时使用)。</summary>
- public static ServiceRegistry Default => _default.Value;
- private readonly object _sync = new object();
- private readonly Dictionary<Type, object> _services = new Dictionary<Type, object>();
- /// <summary>注册/替换一个服务实例(按具体类型索引)。</summary>
- public void Register<T>(T service)
- {
- if (service == null) return;
- lock (_sync) { _services[typeof(T)] = service; }
- }
- /// <summary>移除注册。</summary>
- public void Unregister<T>()
- {
- lock (_sync) { _services.Remove(typeof(T)); }
- }
- /// <inheritdoc />
- public T GetService<T>()
- {
- return (T)GetService(typeof(T));
- }
- /// <inheritdoc />
- public object GetService(Type serviceType)
- {
- if (serviceType == null) return null;
- lock (_sync)
- {
- object svc;
- return _services.TryGetValue(serviceType, out svc) ? svc : null;
- }
- }
- /// <inheritdoc />
- public T GetDevice<T>(string deviceName)
- {
- foreach (var device in GetDevices<T>())
- {
- var named = device as TeamAAS.Global.Devices.INamedDevice;
- if (named == null) continue; // 设备类型未实现 INamedDevice 时无法按名查找
- if (string.Equals(named.Name, deviceName, StringComparison.OrdinalIgnoreCase))
- return device;
- }
- return default(T);
- }
- /// <inheritdoc />
- public IEnumerable<T> GetDevices<T>()
- {
- // IDeviceProvider<TDevice> 带 INamedDevice 约束,此处经反射构造闭合泛型接口后取服务,
- // 保持 GetDevices<T> 对调用方无约束(注册方负责满足约束)。
- var providerType = typeof(TeamAAS.Global.Devices.IDeviceProvider<>).MakeGenericType(typeof(T));
- var provider = GetService(providerType);
- if (provider != null)
- {
- var devices = providerType.GetProperty("Devices")?.GetValue(provider) as IEnumerable<T>;
- if (devices != null)
- {
- foreach (var d in devices) yield return d;
- }
- yield break;
- }
- // 兜底:设备集合本身被当作服务注册(IReadOnlyList<T> 等)
- var list = GetService<System.Collections.Generic.IReadOnlyList<T>>();
- if (list != null)
- {
- foreach (var d in list) yield return d;
- }
- }
- /// <inheritdoc />
- public void Log(string flowName, string nodeName, int level, string message, string category = "Info")
- {
- // 阶段1:转发到控制台,宿主接入 PluginLogger 后替换(避免 SDK 反向依赖 TeamAAS.Global)
- System.Diagnostics.Debug.WriteLine($"[{category}][L{level}][{flowName}/{nodeName}] {message}");
- }
- }
- }
|