public abstract class Parameter : INamed<string>
{
private readonly string name;
private readonly PrimitiveType myType;
private readonly int contextKey;
private readonly ParameterContext context;
private object cachedValue;
public string Name => name;
public ParameterBounds Bounds => getBounds();
public object Value
{
get
{
cachedValue = getValue();
return cachedValue;
}
set
{
ValidTypeException(value);
setValue(value);
cachedValue = value;
}
}
internal double ValueDouble
{
get
{
return (double)getValue();
}
set
{
switch (ValueType)
{
case PrimitiveType.Integer:
setValue((int)value);
break;
case PrimitiveType.Double:
setValue(value);
break;
case PrimitiveType.Single:
setValue((float)value);
break;
case PrimitiveType.Long:
setValue((long)value);
break;
default:
throw new InvalidCastException();
}
}
}
internal object CachedValue
{
get
{
if (cachedValue == null)
{
return Value;
}
return cachedValue;
}
}
internal int Number => ParameterInfoProvider.GetNumber(name);
public object Default => ParameterInfoProvider.GetDefault(name);
public PrimitiveType ValueType => myType;
public ParameterContext Context => context;
public int ContextKey => contextKey;
internal void WithinBoundsException(Controller controller, object value)
{
if (WithinBounds(value) != 0)
{
ExceptionResolver.ResolveThrow(controller, ExceptionResolver.CreateErrorStructure(ErrorCode.ParameterValueOutOfRange));
}
}
internal Parameter(string name, PrimitiveType myType)
: this(name, myType, ParameterContext.System, 0)
{
}
internal Parameter(string name, PrimitiveType myType, ParameterContext context, int contextKey)
{
this.name = name;
this.myType = myType;
this.context = context;
this.contextKey = contextKey;
}
protected abstract ParameterBounds getBounds();
internal void InvalidateCache()
{
cachedValue = null;
}
protected abstract void setValue(object value);
protected abstract object getValue();
internal int WithinBounds(object value)
{
if (!Bounds.Exists)
{
if (value is double d)
{
if (double.IsNegativeInfinity(d) || double.IsNaN(d))
{
return -1;
}
if (double.IsPositiveInfinity(d))
{
return 1;
}
}
else if (value is float f)
{
if (float.IsNegativeInfinity(f) || float.IsNaN(f))
{
return -1;
}
if (float.IsPositiveInfinity(f))
{
return 1;
}
}
return 0;
}
if ((value as IComparable).CompareTo(Bounds.Min) < 0)
{
return -1;
}
if ((value as IComparable).CompareTo(Bounds.Max) > 0)
{
return 1;
}
return 0;
}
internal void ValidTypeException(object value)
{
if (ValueType switch
{
PrimitiveType.Integer => typeof(int),
PrimitiveType.Double => typeof(double),
PrimitiveType.Single => typeof(float),
PrimitiveType.Long => typeof(long),
PrimitiveType.String => typeof(string),
_ => typeof(object),
} != value.GetType())
{
throw new InvalidCastException();
}
}
}
以下是针对 Parameter
抽象类的深度解析,从设计模式到实现细节的全面分析:
1. 核心职责
作为 参数系统的基类,主要功能包括:
类型安全的参数值管理:支持多种原始类型(int/double/float/long/string)
边界验证:自动检查值范围有效性
缓存机制:减少频繁访问底层系统的开销
上下文感知:区分系统级/任务级等不同参数来源
2. 关键设计模式
(1)模板方法模式
抽象钩子方法:强制子类实现特定硬件访问逻辑
通用逻辑复用:边界检查/类型验证等在基类完成
(2)装饰器模式
public object Value {
get {
cachedValue = getValue(); // 实际获取值
return cachedValue;
}
set {
ValidTypeException(value); // 验证类型
setValue(value); // 实际设置值
cachedValue = value; // 更新缓存
}
}
(3)策略模式
internal double ValueDouble {
set {
switch(ValueType) { // 根据类型选择转换策略
case PrimitiveType.Integer: setValue((int)value); break;
case PrimitiveType.Double: setValue(value); break;
// ...
}
}
}
3. 核心组件分析
组件 | 类型/接口 | 功能 |
---|---|---|
ParameterBounds |
值对象 | 存储参数最小/最大值 |
ParameterInfoProvider |
静态类 | 提供元数据(编号/默认值) |
PrimitiveType |
枚举 | 定义支持的参数类型 |
ParameterContext |
枚举 | 参数作用域分类 |
4. 关键流程
(1)值获取流程
(2)值设置流程
5. 类型安全设计
机制 | 实现方式 | 示例 |
---|---|---|
编译时检查 | 泛型约束 | where T : IComparable |
运行时验证 | ValidTypeException |
拒绝 string 赋值给 double 参数 |
安全转换 | ValueDouble 属性 |
自动处理浮点到整型的转换 |
6. 典型子类实现
internal class HardwareParameter : Parameter
{
private readonly IntPtr _deviceHandle;
protected override object getValue() {
double val = 0;
Wrapper.AerParamRead(_deviceHandle, Name, ref val);
return Convert.ChangeType(val, ValueType);
}
protected override void setValue(object value) {
double dVal = Convert.ToDouble(value);
Wrapper.AerParamWrite(_deviceHandle, Name, dVal);
}
protected override ParameterBounds getBounds() {
double min=0, max=0;
Wrapper.AerParamGetBounds(_deviceHandle, Name, ref min, ref max);
return new ParameterBounds(min, max);
}
}
7. 改进建议
线程安全增强
private readonly object _syncLock = new object();
public object Value {
get {
lock(_syncLock) {
if (_cacheExpired) {
cachedValue = getValue();
_cacheExpired = false;
}
return cachedValue;
}
}
}
DI 集成
public interface IParameterFactory {
Parameter Create(string name, ParameterContext ctx);
}
异步支持
public async Task<object> GetValueAsync() {
return await Task.Run(() => Value);
}
更智能的缓存
private DateTime _lastUpdated;
public bool IsCacheValid =>
(DateTime.Now - _lastUpdated) < CacheTimeout;
8. 边界条件处理
边界情况 | 处理方式 | 代码示例 |
---|---|---|
无穷大值 | 特殊检查 | double.IsInfinity(value) |
NaN 值 | 显式拒绝 | throw new ArgumentException |
类型不匹配 | 异常抛出 | ValidTypeException |
超出范围 | 错误代码返回 | WithinBounds() |
总结
该抽象类的设计优势:
良好的扩展性:通过抽象方法支持多种硬件平台
类型安全:严格的运行时类型检查
性能优化:缓存机制减少硬件访问
典型应用于:
CNC系统参数管理
工业控制器配置系统
实时参数监控平台
通过增加响应式编程支持(如 IObservable
)和更细粒度的变更通知,可进一步提升其在现代工业系统中的实用性。