internal static class Global
{
internal static readonly IDictionary<Drive, ComponentType> CoreDriveIdMappings;
public const int MaxAxes = 32;
public const int DefaultImmediateCommandsTask = 0;
public const int DefaultTaskStopTimeout = 10000;
public const string ProgramExtension = ".pgm";
public const string ProductName = "A3200";
public const string AxisNameParameter = "AxisName";
public const string AxisNameRegex = "^([XYZUABCDVWxyzuabcdvw]|([A-Za-z_]{2}[A-Za-z_0-9]*))$";
public static readonly int StringVariableLength;
public const int MaxCollectionRateKHz = 8;
public const string ImmediateCommandsReturnVariableName = "$return";
public static readonly int MaxUserTasks;
internal const string EnumFlagsValueToSkip = "None";
public const TaskId UnknownTask = (TaskId)(-1);
public const string ParamsNs = "http://www.aerotech.com/xsd/Controller/Parameters/2009/";
public const string UpgradableParamsNs = "http://www.aerotech.com/xsd/StandAlone/Parameters/2006/";
public const string SoftwareRegistryKey = "SOFTWARE\\Aerotech\\A3200";
public const string CommunicationServiceRegistryKey = "SOFTWARE\\Aerotech\\A3200\\CommService";
private static BaseParameters defaultParameters;
private static readonly object defaultParametersLock;
private static string helpFilePath;
public static IFileParameterCreator DefaultFileParametersCreator => FileParameterCreatorFactory.Create(new StringReader(InfoResources.parameters));
public static BaseParameters DefaultParameters
{
get
{
if (defaultParameters == null)
{
lock (defaultParametersLock)
{
if (defaultParameters == null)
{
defaultParameters = new BaseParameters(-1, DefaultFileParametersCreator, AxisParameterCategory.Creator, TaskParameterCategory.Creator);
}
}
}
return new BaseParameters((int)defaultParameters.Axes.Mask, new LocalParameterCreator(defaultParameters), AxisParameterCategory.Creator, TaskParameterCategory.Creator);
}
}
internal static string HelpFilePath
{
get
{
if (helpFilePath == null)
{
helpFilePath = "mk:@MSITStore:" + Path.Combine(SoftwareEnvironment.InstallDirFailSafe, string.Format("Help\\{0}.chm", "A3200")) + "::/";
}
return helpFilePath;
}
}
static Global()
{
StringVariableLength = 188;
MaxUserTasks = Enum.GetValues(typeof(TaskId)).Length;
defaultParametersLock = new object();
helpFilePath = null;
CoreDriveIdMappings = new Dictionary<Drive, ComponentType>();
CoreDriveIdMappings.Add(Drive.HARDWARE_TYPE_INVALID, ComponentType.Virtual);
CoreDriveIdMappings.Add(Drive.HARDWARE_NDRIVEHL_REV_A, ComponentType.NdriveHPHL);
CoreDriveIdMappings.Add(Drive.HARDWARE_TYPE_NDRIVEHP_REV_DASH, ComponentType.NdriveHPHL);
CoreDriveIdMappings.Add(Drive.HARDWARE_TYPE_NPAQ_REV_DASH, ComponentType.Npaq);
CoreDriveIdMappings.Add(Drive.HARDWARE_TYPE_NDRIVEHP_REV_A, ComponentType.NdriveHPHL);
CoreDriveIdMappings.Add(Drive.HARDWARE_TYPE_NDRIVECP_REV_DASH, ComponentType.NdriveCP);
CoreDriveIdMappings.Add(Drive.HARDWARE_TYPE_NSERVO2_REV_DASH, ComponentType.Nservo);
CoreDriveIdMappings.Add(Drive.HARDWARE_TYPE_NSERVO4_REV_DASH, ComponentType.Nservo);
CoreDriveIdMappings.Add(Drive.HARDWARE_TYPE_NPAQ_REV_A, ComponentType.Npaq);
CoreDriveIdMappings.Add(Drive.HARDWARE_TYPE_NSERVO1_REV_DASH, ComponentType.Nservo);
CoreDriveIdMappings.Add(Drive.HARDWARE_TYPE_NSERVO3_REV_DASH, ComponentType.Nservo);
CoreDriveIdMappings.Add(Drive.HARDWARE_TYPE_NDRIVECP_REV_A, ComponentType.NdriveCP);
CoreDriveIdMappings.Add(Drive.HARDWARE_TYPE_NDRIVEMP_REV_DASH, ComponentType.NdriveMP);
CoreDriveIdMappings.Add(Drive.HARDWARE_TYPE_NSTEP1_REV_DASH, ComponentType.Nstep);
CoreDriveIdMappings.Add(Drive.HARDWARE_TYPE_NSTEP2_REV_DASH, ComponentType.Nstep);
CoreDriveIdMappings.Add(Drive.HARDWARE_TYPE_NSTEP3_REV_DASH, ComponentType.Nstep);
CoreDriveIdMappings.Add(Drive.HARDWARE_TYPE_NSTEP4_REV_DASH, ComponentType.Nstep);
CoreDriveIdMappings.Add(Drive.HARDWARE_TYPE_NDRIVECL_REV_DASH, ComponentType.NdriveCL);
CoreDriveIdMappings.Add(Drive.HARDWARE_TYPE_NDRIVECP_REV_B, ComponentType.NdriveCP);
CoreDriveIdMappings.Add(Drive.HARDWARE_TYPE_NDRIVEHPE_REV_DASH, ComponentType.NdriveHPe);
CoreDriveIdMappings.Add(Drive.HARDWARE_TYPE_NMARKSSAM2_REV_DASH, ComponentType.NmarkSSaM);
CoreDriveIdMappings.Add(Drive.HARDWARE_TYPE_NMARKSSAM3_REV_DASH, ComponentType.NmarkSSaM);
CoreDriveIdMappings.Add(Drive.HARDWARE_TYPE_NDRIVEHLE_REV_DASH, ComponentType.NdriveHLe);
CoreDriveIdMappings.Add(Drive.HARDWARE_TYPE_NDRIVEML_REV_DASH, ComponentType.NdriveML);
CoreDriveIdMappings.Add(Drive.HARDWARE_TYPE_NDRIVEPMT_REV_DASH, ComponentType.NdrivePMT);
CoreDriveIdMappings.Add(Drive.HARDWARE_TYPE_NDRIVECL_REV_A, ComponentType.NdriveCL);
CoreDriveIdMappings.Add(Drive.HARDWARE_TYPE_SF4_REV_DASH, ComponentType.SensorFusion);
CoreDriveIdMappings.Add(Drive.HARDWARE_TYPE_NMARKCLS2_REV_DASH, ComponentType.NmarkCLS);
CoreDriveIdMappings.Add(Drive.HARDWARE_TYPE_NMARKCLS3_REV_DASH, ComponentType.NmarkCLS);
CoreDriveIdMappings.Add(Drive.HARDWARE_TYPE_NDRIVEFLS_REV_DASH, ComponentType.NdriveFLS);
CoreDriveIdMappings.Add(Drive.HARDWARE_TYPE_NMARKCLS2_REV_A, ComponentType.NmarkCLS);
CoreDriveIdMappings.Add(Drive.HARDWARE_TYPE_NMARKSSAM2_REV_A, ComponentType.NmarkSSaM);
CoreDriveIdMappings.Add(Drive.HARDWARE_TYPE_NMARKSSAM3_REV_A, ComponentType.NmarkSSaM);
CoreDriveIdMappings.Add(Drive.HARDWARE_TYPE_NDRIVEFLS_REV_A, ComponentType.NdriveFLS);
CoreDriveIdMappings.Add(Drive.HARDWARE_TYPE_NDRIVEQL_REV_DASH, ComponentType.NdriveQL);
CoreDriveIdMappings.Add(Drive.HARDWARE_TYPE_NDRIVEQLE_REV_DASH, ComponentType.NdriveQLe);
CoreDriveIdMappings.Add(Drive.HARDWARE_TYPE_NMARKGCL_REV_DASH, ComponentType.NmarkGCL);
CoreDriveIdMappings.Add(Drive.HARDWARE_TYPE_NMARKGCL_REV_A, ComponentType.NmarkGCL);
CoreDriveIdMappings.Add(Drive.HARDWARE_TYPE_HYPERWIRE_GL4_REV_DASH, ComponentType.GL4);
CoreDriveIdMappings.Add(Drive.HARDWARE_TYPE_XR3_REV_DASH_AMP_NONE, ComponentType.XR3_NoAmplifier);
CoreDriveIdMappings.Add(Drive.HARDWARE_TYPE_XR3_REV_DASH_AMP_XSP3, ComponentType.XR3_XSP3);
CoreDriveIdMappings.Add(Drive.HARDWARE_TYPE_XR3_REV_DASH_AMP_XSL3, ComponentType.XR3_XSL3);
CoreDriveIdMappings.Add(Drive.HARDWARE_TYPE_XR3_REV_DASH_AMP_QSL3E, ComponentType.XR3_QSL3e);
CoreDriveIdMappings.Add(Drive.HARDWARE_TYPE_NDRIVEFCL_REV_DASH, ComponentType.NdriveFCL);
CoreDriveIdMappings.Add(Drive.HARDWARE_TYPE_NDRIVEFCL_REV_A, ComponentType.NdriveFCL);
CoreDriveIdMappings.Add(Drive.HARDWARE_TYPE_HYPERWIRE_XL4S_REV_DASH, ComponentType.XL4s);
CoreDriveIdMappings.Add(Drive.HARDWARE_TYPE_XC4_REV_DASH, ComponentType.XC4);
CoreDriveIdMappings.Add(Drive.HARDWARE_TYPE_XC4E_REV_DASH, ComponentType.XC4e);
}
internal static IDictionary<string, TRet> GetEnumNamesValues<TRet>(Type @enum) where TRet : struct
{
Dictionary<string, TRet> dictionary = new Dictionary<string, TRet>();
string[] names = Enum.GetNames(@enum);
foreach (string text in names)
{
if (!(text == "None"))
{
dictionary[text] = (TRet)Convert.ChangeType(Enum.Parse(@enum, text), typeof(TRet));
}
}
return dictionary;
}
internal static ReadOnlyCollection<string> GetEnumActiveBits<TValue>(Type @enum, TValue value) where TValue : struct
{
IDictionary<string, TValue> enumNamesValues = GetEnumNamesValues<TValue>(@enum);
List<string> list = new List<string>();
long num = (long)Convert.ChangeType(value, typeof(long));
foreach (string key in enumNamesValues.Keys)
{
if (!(key == "None"))
{
long num2 = (long)Convert.ChangeType(enumNamesValues[key], typeof(long));
if ((num & num2) == num2)
{
list.Add(key);
}
}
}
return list.AsReadOnly();
}
}
深度分析 Global 静态类
Global
是一个包含全局常量、静态字段和实用方法的静态类,为 A3200 运动控制系统提供核心配置和通用功能。
核心组成部分
1. 常量定义
定义了大量系统级常量:
public const int MaxAxes = 32; // 最大轴数
public const int DefaultTaskStopTimeout = 10000; // 默认任务停止超时(ms)
public const string ProgramExtension = ".pgm"; // 程序文件扩展名
public const string ProductName = "A3200"; // 产品名称
public const string AxisNameParameter = "AxisName"; // 轴名称参数名
public const string AxisNameRegex = "..."; // 轴名称正则表达式
2. 静态字段
internal static readonly IDictionary<Drive, ComponentType> CoreDriveIdMappings;
public static readonly int StringVariableLength;
private static BaseParameters defaultParameters;
private static readonly object defaultParametersLock;
3. 静态属性
public static IFileParameterCreator DefaultFileParametersCreator { get; }
public static BaseParameters DefaultParameters { get; }
internal static string HelpFilePath { get; }
4. 静态构造函数
初始化静态字段和映射关系:
static Global()
{
StringVariableLength = 188;
MaxUserTasks = Enum.GetValues(typeof(TaskId)).Length;
defaultParametersLock = new object();
helpFilePath = null;
// 初始化驱动类型映射
CoreDriveIdMappings = new Dictionary<Drive, ComponentType>();
CoreDriveIdMappings.Add(Drive.HARDWARE_TYPE_INVALID, ComponentType.Virtual);
// ...添加更多映射...
}
5. 实用方法
internal static IDictionary<string, TRet> GetEnumNamesValues<TRet>(Type @enum)
internal static ReadOnlyCollection<string> GetEnumActiveBits<TValue>(Type @enum, TValue value)
关键设计分析
1. 驱动类型映射系统
CoreDriveIdMappings
将底层硬件驱动类型(Drive)映射到系统组件类型(ComponentType):
CoreDriveIdMappings.Add(Drive.HARDWARE_NDRIVEHL_REV_A, ComponentType.NdriveHPHL);
CoreDriveIdMappings.Add(Drive.HARDWARE_TYPE_NPAQ_REV_DASH, ComponentType.Npaq);
// ...共40+种映射...
这种设计:
-
提供硬件抽象层
-
方便系统识别和处理不同类型的驱动
-
在
AxisInfo.AxisType
属性中被使用
2. 默认参数的单例模式
public static BaseParameters DefaultParameters
{
get
{
if (defaultParameters == null)
{
lock (defaultParametersLock) // 线程安全
{
if (defaultParameters == null)
{
defaultParameters = new BaseParameters(...);
}
}
}
return new BaseParameters(...); // 返回新实例(保护性拷贝)
}
}
特点:
-
双重检查锁定保证线程安全
-
每次返回新实例避免外部修改影响内部状态
-
延迟初始化提高启动性能
3. 枚举处理工具方法
提供强大的枚举处理能力:
GetEnumNamesValues
var values = Global.GetEnumNamesValues<int>(typeof(DriveState));
// 返回 { "Enabled":1, "Disabled":2, ... }
GetEnumActiveBits
var activeBits = Global.GetEnumActiveBits(DriveStatus.Faulted | DriveStatus.Enabled);
// 返回 ["Faulted", "Enabled"]
这些方法:
-
支持泛型返回值类型
-
自动跳过"None"值
-
支持标志枚举的位运算分析
4. 帮助系统集成
internal static string HelpFilePath
{
get
{
if (helpFilePath == null)
{
helpFilePath = "mk:@MSITStore:" +
Path.Combine(SoftwareEnvironment.InstallDirFailSafe,
"Help\\A3200.chm") + "::/";
}
return helpFilePath;
}
}
提供编译帮助文件的访问路径,支持MS Help 2.0格式。
典型使用场景
1. 获取驱动类型
var driveType = Drive.HARDWARE_TYPE_NDRIVECP_REV_A;
var componentType = Global.CoreDriveIdMappings[driveType];
// componentType = ComponentType.NdriveCP
2. 使用默认参数
var parameters = Global.DefaultParameters;
var axisName = parameters.Axes[0].AxisNameParameter.Value;
3. 分析标志枚举
var status = AxisStatus.Moving | AxisStatus.Enabled;
var activeStatuses = Global.GetEnumActiveBits(status);
// 返回 ["Moving", "Enabled"]
设计优势
-
集中管理:所有全局配置和常量集中存放
-
线程安全:关键资源使用锁保护
-
类型安全:泛型方法保证类型正确性
-
性能优化:延迟初始化和缓存提高性能
-
可扩展性:方便添加新的全局配置
潜在改进建议
-
配置外部化:将部分常量移至配置文件
-
更细粒度锁:减少锁竞争可能性
-
枚举缓存:缓存GetEnumNamesValues结果
-
国际化支持:为帮助系统添加多语言支持
-
更安全的字典访问:添加TryGetValue保护
总结
Global
类是A3200控制系统的核心基础设施,提供:
-
统一的全局配置访问点
-
硬件抽象映射层
-
强大的枚举处理工具
-
线程安全的单例管理
-
系统级常量的集中定义
这种设计模式非常适合工业控制软件这类需要严格管理全局状态和配置的系统。