internal class ControllerParameter<T> : TypedParameter<T> where T : IComparable
{
private readonly Controller controller;
internal ControllerParameter(Controller controller, string name, PrimitiveType myType)
: this(controller, name, myType, ParameterContext.System, 0)
{
}
internal ControllerParameter(Controller controller, string name, PrimitiveType myType, ParameterContext context, int contextKey)
: base(name, myType, context, contextKey)
{
this.controller = controller;
}
protected override object getValue()
{
int number = ParameterInfoProvider.GetNumber(base.Name);
if (base.ValueType == PrimitiveType.String)
{
StringBuilder stringBuilder = new StringBuilder(10000);
ExceptionResolver.ResolveThrow(controller, Wrapper.AerParmGetValueString(controller.Handle.Value, (int)base.Context, base.ContextKey, number, stringBuilder, stringBuilder.Capacity));
return stringBuilder.ToString();
}
double pdValue_ = 0.0;
ExceptionResolver.ResolveThrow(controller, Wrapper.AerParmGetValue(controller.Handle.Value, (int)base.Context, base.ContextKey, number, ref pdValue_));
TypeCode typeCode = TypeCode.Object;
switch (base.ValueType)
{
case PrimitiveType.Double:
typeCode = TypeCode.Double;
break;
case PrimitiveType.Integer:
typeCode = TypeCode.Int32;
break;
case PrimitiveType.Long:
typeCode = TypeCode.Int64;
break;
case PrimitiveType.Single:
typeCode = TypeCode.Single;
break;
}
return Convert.ChangeType(pdValue_, typeCode);
}
protected override void setValue(object value)
{
int number = ParameterInfoProvider.GetNumber(base.Name);
if (base.ValueType == PrimitiveType.String)
{
string text = (string)value;
ExceptionResolver.ResolveThrow(controller, Wrapper.AerParmSetValueString(controller.Handle.Value, (int)base.Context, base.ContextKey, number, text, text.Length));
}
else
{
double dValue_ = Convert.ToDouble(value);
ExceptionResolver.ResolveThrow(controller, Wrapper.AerParmSetValue(controller.Handle.Value, (int)base.Context, base.ContextKey, number, dValue_));
}
}
}
以下是针对 ControllerParameter<T>
类的详细中文解析:
1. 类定义与泛型约束
internal class ControllerParameter<T> : TypedParameter<T> where T : IComparable
-
作用:
这是一个 内部类(仅限当前程序集访问),继承自泛型基类TypedParameter<T>
,并约束泛型类型T
必须实现IComparable
接口(确保值可比较)。
2. 构造函数
简化构造
internal ControllerParameter(Controller controller, string name, PrimitiveType myType)
: this(controller, name, myType, ParameterContext.System, 0)
-
功能:
提供快速初始化,默认设置参数上下文为System
,上下文键为0
,并转发到完整构造函数。
完整构造
internal ControllerParameter(Controller controller, string name, PrimitiveType myType,
ParameterContext context, int contextKey)
: base(name, myType, context, contextKey)
{
this.controller = controller;
}
-
关键点:
-
通过
base
调用基类构造函数,初始化参数名称、类型、上下文和键。 -
存储
controller
实例引用,用于后续与底层硬件/驱动交互。
-
3. 核心方法解析
getValue()
:获取参数值
protected override object getValue()
{
int number = ParameterInfoProvider.GetNumber(base.Name); // 获取参数编号
if (base.ValueType == PrimitiveType.String) // 字符串类型特殊处理
{
StringBuilder stringBuilder = new StringBuilder(10000);
ExceptionResolver.ResolveThrow(controller,
Wrapper.AerParmGetValueString(controller.Handle.Value, (int)base.Context,
base.ContextKey, number, stringBuilder, stringBuilder.Capacity));
return stringBuilder.ToString();
}
double pdValue_ = 0.0;
ExceptionResolver.ResolveThrow(controller,
Wrapper.AerParmGetValue(controller.Handle.Value, (int)base.Context,
base.ContextKey, number, ref pdValue_));
// 根据类型转换返回值
TypeCode typeCode = TypeCode.Object;
switch (base.ValueType)
{
case PrimitiveType.Double: typeCode = TypeCode.Double; break;
case PrimitiveType.Integer: typeCode = TypeCode.Int32; break;
case PrimitiveType.Long: typeCode = TypeCode.Int64; break;
case PrimitiveType.Single: typeCode = TypeCode.Single; break;
}
return Convert.ChangeType(pdValue_, typeCode);
}
-
流程:
-
通过
ParameterInfoProvider
将参数名转换为唯一编号。 -
字符串类型:调用原生方法
AerParmGetValueString
,预分配StringBuilder
缓冲区接收结果。 -
数值类型:
-
调用
AerParmGetValue
获取double
类型的原始值。 -
根据
PrimitiveType
转换为目标类型(如int
,float
等)。
-
-
-
异常处理:通过
ExceptionResolver.ResolveThrow
统一处理原生调用错误。
setValue()
:设置参数值
protected override void setValue(object value)
{
int number = ParameterInfoProvider.GetNumber(base.Name);
if (base.ValueType == PrimitiveType.String)
{
string text = (string)value;
ExceptionResolver.ResolveThrow(controller,
Wrapper.AerParmSetValueString(controller.Handle.Value, (int)base.Context,
base.ContextKey, number, text, text.Length));
}
else
{
double dValue_ = Convert.ToDouble(value); // 统一转为double
ExceptionResolver.ResolveThrow(controller,
Wrapper.AerParmSetValue(controller.Handle.Value, (int)base.Context,
base.ContextKey, number, dValue_));
}
}
-
关键逻辑:
-
字符串:直接调用原生方法
AerParmSetValueString
设置。 -
数值:先统一转为
double
,再通过AerParmSetValue
设置。
-
-
安全性:依赖
Convert.ToDouble
和异常处理器保证类型安全。
4. 设计意图分析
-
抽象层次:
封装了与底层控制器(如PLC、嵌入式设备)的参数交互细节,向上提供类型安全的接口。 -
性能优化:
-
字符串处理使用预分配的
StringBuilder
避免频繁内存分配。 -
数值类型统一通过
double
中转,简化原生接口调用。
-
-
扩展性:
通过PrimitiveType
和泛型支持多种数据类型,未来可轻松添加新类型。
5. 典型使用场景
假设有一个温度控制器,其参数可能如下使用:
// 定义温度参数(double类型)
var tempParam = new ControllerParameter<double>(controller, "Temperature", PrimitiveType.Double);
// 设置温度值
tempParam.setValue(25.5);
// 读取当前温度
double currentTemp = (double)tempParam.getValue();
总结
该类是 硬件控制层与业务逻辑层之间的适配器,核心价值在于:
-
类型安全:通过泛型和类型检查避免运行时错误。
-
统一异常处理:集中管理原生调用错误。
-
简化调用:隐藏复杂的原生API细节,提供直观的C#接口。