972 lines
45 KiB
C#
972 lines
45 KiB
C#
using System;
|
||
using System.Collections.Generic;
|
||
using System.ComponentModel;
|
||
using System.Linq;
|
||
using System.Reflection;
|
||
using System.Runtime.Serialization;
|
||
using System.Text;
|
||
using System.Threading.Tasks;
|
||
using System.Windows.Controls;
|
||
|
||
namespace Future.Contract
|
||
{
|
||
/// <summary>
|
||
/// 用于将一个属性标记为一个可以使用参数设计器编辑的参数值
|
||
/// </summary>
|
||
[DataContract]
|
||
[AttributeUsage(AttributeTargets.Property, AllowMultiple = false, Inherited = true)]
|
||
public class ParameterDefineAttribute : Attribute, INotifyPropertyChanged, IFuture
|
||
{
|
||
public event PropertyChangedEventHandler PropertyChanged;
|
||
|
||
/// <summary>
|
||
/// 参数的归类信息
|
||
/// </summary>
|
||
[DataMember]
|
||
private EParameterKind mKind = EParameterKind.General;
|
||
public EParameterKind Kind
|
||
{
|
||
get => this.mKind;
|
||
set
|
||
{
|
||
if (this.mKind != value)
|
||
{
|
||
this.mKind = value;
|
||
this.PropertyChanged(this, new PropertyChangedEventArgs("Kind"));
|
||
}
|
||
}
|
||
}
|
||
/// <summary>
|
||
/// 用于存储自定义参数设置器的类型
|
||
/// </summary>
|
||
[DataMember]
|
||
private Type mSetterType = null;
|
||
/// <summary>
|
||
/// 自定义参数设置器使用的类型定义
|
||
/// </summary>
|
||
public Type SetterType
|
||
{
|
||
get => this.mSetterType;
|
||
set { this.mSetterType = value; }
|
||
}
|
||
/// <summary>
|
||
/// 用于存储参数数据类型的内部变量
|
||
/// </summary>
|
||
[DataMember]
|
||
private EParameterType mType = EParameterType.Number;
|
||
/// <summary>
|
||
/// 参数的数据类型
|
||
/// </summary>
|
||
public EParameterType Type
|
||
{
|
||
get => this.mType;
|
||
set
|
||
{
|
||
if (this.mType != value)
|
||
{
|
||
this.mType = value;
|
||
this.PropertyChanged(this, new PropertyChangedEventArgs("Type"));
|
||
}
|
||
}
|
||
}
|
||
/// <summary>
|
||
/// 用于存储参数名称的内部变量
|
||
/// </summary>
|
||
[DataMember]
|
||
private string mName = "PName";
|
||
/// <summary>
|
||
/// 参数的标识名称
|
||
/// </summary>
|
||
public string Name
|
||
{
|
||
get => this.mName;
|
||
set
|
||
{
|
||
if (this.mName != value)
|
||
{
|
||
this.mName = value;
|
||
this.PropertyChanged(this, new PropertyChangedEventArgs("Name"));
|
||
}
|
||
}
|
||
}
|
||
/// <summary>
|
||
/// 用于存储参数标题名称的内部变量
|
||
/// </summary>
|
||
[DataMember]
|
||
private string mTitle = "动态参数";
|
||
/// <summary>
|
||
/// 参数的标题
|
||
/// </summary>
|
||
public string Title
|
||
{
|
||
get => this.mTitle;
|
||
set
|
||
{
|
||
if (mTitle != value)
|
||
{
|
||
mTitle = value;
|
||
this.PropertyChanged(this, new PropertyChangedEventArgs("Title"));
|
||
}
|
||
}
|
||
}
|
||
/// <summary>
|
||
/// 用于存储参数描述信息的内部变量
|
||
/// </summary>
|
||
[DataMember]
|
||
private string mRemark = "动态参数";
|
||
/// <summary>
|
||
/// 参数描述
|
||
/// </summary>
|
||
public string Remark
|
||
{
|
||
get => this.mRemark;
|
||
set
|
||
{
|
||
if (mRemark != value)
|
||
{
|
||
mRemark = value;
|
||
this.PropertyChanged(this, new PropertyChangedEventArgs("Remark"));
|
||
}
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// 用于存储以文本格式记录的参数默认值的内部变量
|
||
/// </summary>
|
||
[DataMember]
|
||
private string mDefault = "";
|
||
/// <summary>
|
||
/// 以文本形式存储参数的默认取值或是可取值集合
|
||
/// </summary>
|
||
public string Default
|
||
{
|
||
get => this.mDefault;
|
||
set
|
||
{
|
||
if (this.mDefault != value)
|
||
{
|
||
mDefault = value;
|
||
this.PropertyChanged(this, new PropertyChangedEventArgs("Default"));
|
||
}
|
||
}
|
||
}
|
||
/// <summary>
|
||
/// 为设计器指示ValueExp是值还是引用
|
||
/// </summary>
|
||
public bool IsLinked { get => (this.Expression?.StartsWith(FutureInstruct.PR_StartString)) ?? false; }
|
||
/// <summary>
|
||
/// 用于存储值表达式的内部变量
|
||
/// </summary>
|
||
[DataMember]
|
||
private string mExpression = "";
|
||
/// <summary>
|
||
/// 参数引用表达式,设计器操作的永远是这个属性而非真正的参数值Value属性
|
||
/// </summary>
|
||
public string Expression
|
||
{
|
||
get => this.mExpression;
|
||
set
|
||
{
|
||
if (this.mExpression != value)
|
||
{
|
||
this.mExpression = value;
|
||
this.PropertyChanged(this, new PropertyChangedEventArgs("ValueExp"));
|
||
this.PropertyChanged(this, new PropertyChangedEventArgs("IsLinked"));
|
||
}
|
||
}
|
||
}
|
||
/// <summary>
|
||
/// 用于存储候选值的内部变量
|
||
/// </summary>
|
||
[DataMember]
|
||
private string mCandidate = "";
|
||
/// <summary>
|
||
/// 候选值:如果类型存在候选值则必须使用标准Json格式描述;可以是JsonObject格式或是JsonArray格式的任意一种描述方式
|
||
/// </summary>
|
||
public string Candidate
|
||
{
|
||
get => this.mCandidate;
|
||
set
|
||
{
|
||
if (this.mCandidate != value)
|
||
{
|
||
this.Candidate = value;
|
||
this.PropertyChanged(this, new PropertyChangedEventArgs("Candidate"));
|
||
}
|
||
}
|
||
}
|
||
/// <summary>
|
||
/// 候选词字典实例专为设计器使用
|
||
/// </summary>
|
||
public Dictionary<string, object> CandidateMapping
|
||
{
|
||
get
|
||
{
|
||
Dictionary<string, object> dicCandidate = null;
|
||
if (!string.IsNullOrEmpty(this.Candidate))
|
||
{
|
||
try
|
||
{
|
||
//有可能是JsonArray定义的候选词集合
|
||
if (this.Candidate[0] == '[')
|
||
{
|
||
List<object> list = this.Candidate.Decode4Json<List<object>>();
|
||
foreach (var item in list) dicCandidate.Add(item.ToString(), item);
|
||
}
|
||
//有可能是JsonObject定义的候选词集合
|
||
else if (this.Candidate[0] == '{') dicCandidate = this.Candidate.Decode4Json<Dictionary<string, object>>();
|
||
//不是有效的Json定义格式
|
||
else dicCandidate = new Dictionary<string, object>();
|
||
}
|
||
catch
|
||
{
|
||
//Json格式有问题;丢弃异常,不处理;返回一个空的字典,以免外部引用时出错
|
||
dicCandidate = new Dictionary<string, object>();
|
||
}
|
||
}
|
||
return dicCandidate;
|
||
}
|
||
}
|
||
/// <summary>
|
||
/// 是否只允许使用候选值进行选择
|
||
/// </summary>
|
||
[DataMember]
|
||
private bool mIsCandidateOnly = false;
|
||
/// <summary>
|
||
/// 是否只允许使用候选值进行选择
|
||
/// </summary>
|
||
public bool IsCandidateOnly
|
||
{
|
||
get
|
||
{
|
||
//部分类型此项设置无效,只能使用选择模式
|
||
if (this.Type == EParameterType.Boolean) return true;
|
||
else return mIsCandidateOnly;
|
||
}
|
||
set { this.mIsCandidateOnly = value; }
|
||
}
|
||
|
||
/// <summary>
|
||
/// 标记一个参数是否允许重新定义,数据类型,参数名称,参数标题,参数描述
|
||
/// </summary>
|
||
[DataMember]
|
||
public bool AllowRefine { get; set; } = false;
|
||
/// <summary>
|
||
/// 标记参数是否允许重设单位名称
|
||
/// </summary>
|
||
[DataMember]
|
||
public bool AllowReUnit { get; set; } = true;
|
||
/// <summary>
|
||
/// 参数的单位名称字段
|
||
/// </summary>
|
||
[DataMember]
|
||
private string mUnitName;
|
||
/// <summary>
|
||
/// 参数的单位名称
|
||
/// </summary>
|
||
public string UnitName
|
||
{
|
||
get => this.mUnitName;
|
||
set
|
||
{
|
||
if (this.mUnitName == value) return;
|
||
mUnitName = value;
|
||
this.PropertyChanged(this, new PropertyChangedEventArgs("UnitName"));
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// 标记一个属性是否允许用户编辑
|
||
/// </summary>
|
||
[DataMember]
|
||
public bool IsReadOnly { get; set; } = true;
|
||
/// <summary>
|
||
/// 设置一个参数的排序,不可为负
|
||
/// </summary>
|
||
[DataMember]
|
||
public int DesignSort { get; set; } = 0;
|
||
/// <summary>
|
||
/// 参数设计器中显示的参数分组名
|
||
/// </summary>
|
||
[DataMember]
|
||
public string GroupName { get; set; } = "";
|
||
public PropertyInfo AttachProperty { get; internal set; }
|
||
public object AttachObject { get; internal set; }
|
||
/// <summary>
|
||
/// 克隆当前对象
|
||
/// </summary>
|
||
/// <returns>克隆后的对象</returns>
|
||
public IFuture Clone()
|
||
{
|
||
return new ParameterDefineAttribute()
|
||
{
|
||
Name = this.Name,
|
||
AllowRefine = this.AllowRefine,
|
||
AllowReUnit = this.AllowReUnit,
|
||
AttachObject = this.AttachObject,
|
||
AttachProperty = this.AttachProperty,
|
||
Default = this.Default,
|
||
DesignSort = this.DesignSort,
|
||
GroupName = this.GroupName,
|
||
IsReadOnly = this.IsReadOnly,
|
||
Kind = this.Kind,
|
||
Remark = this.Remark,
|
||
Title = this.Title,
|
||
Type = this.Type,
|
||
UnitName = this.UnitName,
|
||
|
||
Expression = this.Expression
|
||
};
|
||
}
|
||
/// <summary>
|
||
/// 对象属性覆盖:用引用对象属性覆盖当前对象属性,对引用属性只会实现引用赋值,不做深拷贝
|
||
/// </summary>
|
||
/// <param name="refer">用于覆盖当前对象属性的源对象</param>
|
||
/// <returns>如果源对象类型不是当前对象或是其子类类型则直接覆盖失败,返回False</returns>
|
||
public bool Cover(IFuture refer)
|
||
{
|
||
if (refer == null) return false;
|
||
ParameterDefineAttribute pda = refer as ParameterDefineAttribute;
|
||
if (pda == null) return false;
|
||
|
||
this.Name = pda.Name;
|
||
this.AllowRefine = pda.AllowRefine;
|
||
this.AllowRefine = pda.AllowRefine;
|
||
this.AttachObject = pda.AttachObject;
|
||
this.AttachProperty = pda.AttachProperty;
|
||
this.Default = pda.Default;
|
||
this.DesignSort = pda.DesignSort;
|
||
this.GroupName = pda.GroupName;
|
||
this.IsReadOnly = pda.IsReadOnly;
|
||
this.Kind = pda.Kind;
|
||
this.Remark = pda.Remark;
|
||
this.Title = pda.Title;
|
||
this.Type = pda.Type;
|
||
this.UnitName = pda.UnitName;
|
||
|
||
this.Expression = pda.Expression;
|
||
|
||
return true;
|
||
}
|
||
/// <summary>
|
||
/// 校验当前参数的设置是否有效;主要校验【Default:默认值】、【ValueExp=值表达式】【Candidate:候选词】;不检查[""]与[null]
|
||
/// </summary>
|
||
/// <param name="owner">参数归属</param>
|
||
/// <returns>如果校验失败则返回错误信息</returns>
|
||
public string Verify(string owner = null)
|
||
{
|
||
EParameterType type = this.Type;
|
||
string ownerName = owner ?? (this.AttachObject as IConfigurableObject)?.Title;
|
||
string etypeName = type.GetParameterTypeName();
|
||
string eValue = this.mExpression ?? "";
|
||
string dValue = this.mDefault ?? "";
|
||
string cValue = this.mCandidate ?? "";
|
||
|
||
StringBuilder result = new StringBuilder();
|
||
switch (type)
|
||
{
|
||
case EParameterType.Boolean:
|
||
{
|
||
bool sign = true;
|
||
bool value = false;
|
||
//检查默认值表达式,忽略空值[null]与[""]
|
||
if (dValue != "")
|
||
{
|
||
sign = bool.TryParse(dValue, out value);
|
||
if (!sign) result.AppendLine($"【{owner}】的参数【{this.Title}】的“默认值”【 {dValue} 】不是有效的“{etypeName}”值;请重新设置!");
|
||
}
|
||
//检查实际值表达式,忽略空值[null]与[""]和上下文引用表达式
|
||
if (eValue != "" && !eValue.StartsWith(FutureInstruct.PR_StartString))
|
||
{
|
||
sign = bool.TryParse(eValue, out value);
|
||
if (!sign) result.AppendLine($"【{owner}】的参数【{this.Title}】的“设置值”【{eValue}】不是有效的“{etypeName}”值;请重新设置!");
|
||
}
|
||
//检查候选词表达式,忽略空值[null]与[""]
|
||
if (cValue != "" && this.CandidateMapping.Count == 0) result.AppendLine($"【{owner}】的参数【{this.Title}】的“候选值”集合【{cValue}】格式不是有效的“非空”JsonArray或JsonObject格式!");
|
||
else
|
||
{
|
||
foreach (object cval in this.CandidateMapping.Values)
|
||
{
|
||
if (!(cval is bool))
|
||
{
|
||
result.AppendLine($"【{owner}】的参数【{this.Title}】的“候选值”集合中存在非布尔值【{(cval?.ToString()) ?? ""}】;请重新设置!");
|
||
break;
|
||
}
|
||
}
|
||
}
|
||
}
|
||
break;
|
||
case EParameterType.DateTime:
|
||
{
|
||
bool sign = true;
|
||
DateTime value = DateTime.MinValue;
|
||
if (dValue != "")
|
||
{
|
||
sign = DateTime.TryParse(dValue, out value);
|
||
if (!sign) result.AppendLine($"【{owner}】的参数【{this.Title}】的“默认值”【 {dValue} 】不是有效的“{etypeName}”值;请重新设置!");
|
||
}
|
||
if (eValue != "" && !eValue.StartsWith(FutureInstruct.PR_StartString))
|
||
{
|
||
sign = DateTime.TryParse(eValue, out value);
|
||
if (!sign) result.AppendLine($"【{owner}】的参数【{this.Title}】的“设置值”【{eValue}】不是有效的“{etypeName}”值;请重新设置!");
|
||
}
|
||
if (cValue != "" && this.CandidateMapping.Count == 0) result.AppendLine($"【{owner}】的参数【{this.Title}】的“候选值”集合【{cValue}】格式不是有效的“非空”JsonArray或JsonObject格式!");
|
||
else
|
||
{
|
||
foreach (object cval in this.CandidateMapping.Values)
|
||
{
|
||
if (!(cval is DateTime))
|
||
{
|
||
result.AppendLine($"【{owner}】的参数【{this.Title}】的“候选值”集合中存在非布尔值【{(cval?.ToString()) ?? ""}】;请重新设置!");
|
||
break;
|
||
}
|
||
}
|
||
}
|
||
}
|
||
break;
|
||
case EParameterType.Enums:
|
||
{
|
||
bool sign = true;
|
||
int value = 0;
|
||
if (dValue != "")
|
||
{
|
||
sign = int.TryParse(dValue, out value);
|
||
if (!sign) result.AppendLine($"【{owner}】的参数【{this.Title}】的“默认值”【 {dValue} 】不是有效的“{etypeName}”值;请重新设置!");
|
||
}
|
||
if (eValue != "" && eValue.StartsWith(FutureInstruct.PR_StartString))
|
||
{
|
||
sign = int.TryParse(eValue, out value);
|
||
if (!sign) result.AppendLine($"【{owner}】的参数【{this.Title}】的“设置值”【{eValue}】不是有效的“{etypeName}”值;请重新设置!");
|
||
}
|
||
if (cValue != "" && this.CandidateMapping.Count == 0) result.AppendLine($"【{owner}】的参数【{this.Title}】的“候选值”集合【{cValue}】格式不是有效的“非空”JsonArray或JsonObject格式!");
|
||
else
|
||
{
|
||
foreach (object cval in this.CandidateMapping.Values)
|
||
{
|
||
if (!(cval is int))
|
||
{
|
||
result.AppendLine($"【{owner}】的参数【{this.Title}】的“候选值”集合中存在非布尔值【{(cval?.ToString()) ?? ""}】;请重新设置!");
|
||
break;
|
||
}
|
||
}
|
||
}
|
||
}
|
||
break;
|
||
case EParameterType.Integer:
|
||
{
|
||
bool sign = true;
|
||
int value = 0;
|
||
if (dValue != "")
|
||
{
|
||
sign = int.TryParse(dValue, out value);
|
||
if (!sign) result.AppendLine($"【{owner}】的参数【{this.Title}】的“默认值”【 {dValue} 】不是有效的“{etypeName}”值;请重新设置!");
|
||
}
|
||
if (eValue != "" && eValue.StartsWith(FutureInstruct.PR_StartString))
|
||
{
|
||
sign = int.TryParse(eValue, out value);
|
||
if (!sign) result.AppendLine($"【{owner}】的参数【{this.Title}】的“设置值”【{eValue}】不是有效的“{etypeName}”值;请重新设置!");
|
||
}
|
||
if (cValue != "" && this.CandidateMapping.Count == 0) result.AppendLine($"【{owner}】的参数【{this.Title}】的“候选值”集合【{cValue}】格式不是有效的“非空”JsonArray或JsonObject格式!");
|
||
else
|
||
{
|
||
foreach (object cval in this.CandidateMapping.Values)
|
||
{
|
||
if (!(cval is int))
|
||
{
|
||
result.AppendLine($"【{owner}】的参数【{this.Title}】的“候选值”集合中存在非布尔值【{(cval?.ToString()) ?? ""}】;请重新设置!");
|
||
break;
|
||
}
|
||
}
|
||
}
|
||
}
|
||
break;
|
||
case EParameterType.Number:
|
||
{
|
||
bool sign = true;
|
||
double value = 0;
|
||
if (dValue != "")
|
||
{
|
||
sign = double.TryParse(dValue, out value);
|
||
if (!sign) result.AppendLine($"【{owner}】的参数【{this.Title}】的“默认值”【 {dValue} 】不是有效的“{etypeName}”值;请重新设置!");
|
||
}
|
||
if (eValue != "" && eValue.StartsWith(FutureInstruct.PR_StartString))
|
||
{
|
||
sign = double.TryParse(eValue, out value);
|
||
if (!sign) result.AppendLine($"【{owner}】的参数【{this.Title}】的“设置值”【{eValue}】不是有效的“{etypeName}”值;请重新设置!");
|
||
}
|
||
if (cValue != "" && this.CandidateMapping.Count == 0) result.AppendLine($"【{owner}】的参数【{this.Title}】的“候选值”集合【{cValue}】格式不是有效的“非空”JsonArray或JsonObject格式!");
|
||
else
|
||
{
|
||
foreach (object cval in this.CandidateMapping.Values)
|
||
{
|
||
if (!(cval is double))
|
||
{
|
||
result.AppendLine($"【{owner}】的参数【{this.Title}】的“候选值”集合中存在非布尔值【{(cval?.ToString()) ?? ""}】;请重新设置!");
|
||
break;
|
||
}
|
||
}
|
||
}
|
||
}
|
||
break;
|
||
case EParameterType.String: { } break;//不校验
|
||
case EParameterType.RichText: { } break;//不校验
|
||
case EParameterType.Variant: { } break;//不校验
|
||
case EParameterType.IntArray://不校验候选值
|
||
{
|
||
if (dValue != "")
|
||
{
|
||
try { dValue.Decode4Json<List<int>>(); }
|
||
catch { result.AppendLine($"【{owner}】的参数【{this.Title}】的“默认值”【 {dValue} 】不是有效的“{etypeName}”值;请使用标准JsonArray格式设置!"); }
|
||
}
|
||
if (eValue != "")
|
||
{
|
||
try { eValue.Decode4Json<List<int>>(); }
|
||
catch { result.AppendLine($"【{owner}】的参数【{this.Title}】的“设置值”【 {eValue} 】不是有效的“{etypeName}”值;请使用标准JsonArray格式设置!"); }
|
||
}
|
||
}
|
||
break;
|
||
case EParameterType.NumArray://不校验候选值
|
||
{
|
||
if (dValue != "")
|
||
{
|
||
try { dValue.Decode4Json<List<double>>(); }
|
||
catch { result.AppendLine($"【{owner}】的参数【{this.Title}】的“默认值”【 {dValue} 】不是有效的“{etypeName}”值;请使用标准JsonArray格式设置!"); }
|
||
}
|
||
if (eValue != "")
|
||
{
|
||
try { eValue.Decode4Json<List<double>>(); }
|
||
catch { result.AppendLine($"【{owner}】的参数【{this.Title}】的“设置值”【 {eValue} 】不是有效的“{etypeName}”值;请使用标准JsonArray格式设置!"); }
|
||
}
|
||
}
|
||
break;
|
||
case EParameterType.TxtArray:
|
||
{
|
||
if (dValue != "")
|
||
{
|
||
try { dValue.Decode4Json<List<string>>(); }
|
||
catch { result.AppendLine($"【{owner}】的参数【{this.Title}】的“默认值”【 {dValue} 】不是有效的“{etypeName}”值;请使用标准JsonArray格式设置!"); }
|
||
}
|
||
if (eValue != "")
|
||
{
|
||
try { eValue.Decode4Json<List<string>>(); }
|
||
catch { result.AppendLine($"【{owner}】的参数【{this.Title}】的“设置值”【 {eValue} 】不是有效的“{etypeName}”值;请使用标准JsonArray格式设置!"); }
|
||
}
|
||
}
|
||
break;
|
||
case EParameterType.ValArray:
|
||
{
|
||
if (dValue != "")
|
||
{
|
||
try { dValue.Decode4Json<List<object>>(); }
|
||
catch { result.AppendLine($"【{owner}】的参数【{this.Title}】的“默认值”【 {dValue} 】不是有效的“{etypeName}”值;请使用标准JsonArray格式设置!"); }
|
||
}
|
||
if (eValue != "")
|
||
{
|
||
try { eValue.Decode4Json<List<object>>(); }
|
||
catch { result.AppendLine($"【{owner}】的参数【{this.Title}】的“设置值”【 {eValue} 】不是有效的“{etypeName}”值;请使用标准JsonArray格式设置!"); }
|
||
}
|
||
}
|
||
break;
|
||
default://暂时先不校验候选值
|
||
{
|
||
if (dValue != "")
|
||
{
|
||
dValue = dValue.ToUpper();
|
||
if (dValue.StartsWith("0X")) dValue = dValue.Substring(2);
|
||
bool sign = true;
|
||
foreach (char c in dValue)
|
||
{
|
||
if (c < 48 || c > 70 || (c > 57 && c < 65))
|
||
{
|
||
sign = false;
|
||
break;
|
||
}
|
||
}
|
||
if (!sign) result.AppendLine($"【{owner}】的参数【{this.Title}】的“默认值”【 {dValue} 】不是有效的“{etypeName}”值;请使用标准16进制字符串表示!");
|
||
}
|
||
if (eValue != "")
|
||
{
|
||
eValue = eValue.ToUpper();
|
||
if (eValue.StartsWith("0X")) eValue = eValue.Substring(2);
|
||
bool sign = true;
|
||
foreach (char c in eValue)
|
||
{
|
||
if (c < 48 || c > 70 || (c > 57 && c < 65))
|
||
{
|
||
sign = false;
|
||
break;
|
||
}
|
||
}
|
||
if (!sign) result.AppendLine($"【{owner}】的参数【{this.Title}】的“设置值”【 {eValue} 】不是有效的“{etypeName}”值;请使用标准16进制字符串表示!");
|
||
}
|
||
switch (type)
|
||
{
|
||
case EParameterType.Byte:
|
||
{
|
||
if (dValue != "" && dValue.Length != 2) result.AppendLine($"【{owner}】的参数【{this.Title}】的“默认值”【 {dValue} 】应该是“0x”引导的{2}位16进制数,例如“0xA1”!");
|
||
if (eValue != "" && eValue.Length != 2) result.AppendLine($"【{owner}】的参数【{this.Title}】的“设置值”【 {eValue} 】应该是“0x”引导的{2}位16进制数,例如“0xA1”!");
|
||
}
|
||
break;
|
||
case EParameterType.Word:
|
||
{
|
||
if (dValue != "" && dValue.Length != 4) result.AppendLine($"【{owner}】的参数【{this.Title}】的“默认值”【 {dValue} 】应该是“0x”引导的{4}位16进制数,例如“0xA123”!");
|
||
if (eValue != "" && eValue.Length != 4) result.AppendLine($"【{owner}】的参数【{this.Title}】的“设置值”【 {eValue} 】应该是“0x”引导的{4}位16进制数,例如“0xA123”!");
|
||
}
|
||
break;
|
||
case EParameterType.DWord:
|
||
{
|
||
if (dValue != "" && dValue.Length != 4) result.AppendLine($"【{owner}】的参数【{this.Title}】的“默认值”【 {dValue} 】应该是“0x”引导的{4}位16进制数,例如“0xA1234567”!");
|
||
if (eValue != "" && eValue.Length != 8) result.AppendLine($"【{owner}】的参数【{this.Title}】的“设置值”【 {eValue} 】应该是“0x”引导的{8}位16进制数,例如“0xA1234567”!");
|
||
}
|
||
break;
|
||
case EParameterType.LWord:
|
||
{
|
||
if (dValue != "" && dValue.Length != 4) result.AppendLine($"【{owner}】的参数【{this.Title}】的“默认值”【 {dValue} 】应该是“0x”引导的{4}位16进制数,例如“0x0123456789ABCDEF”!");
|
||
if (eValue != "" && eValue.Length != 16) result.AppendLine($"【{owner}】的参数【{this.Title}】的“设置值”【 {eValue} 】应该是“0x”引导的{16}位16进制数,例如“0x0123456789ABCDEF”!");
|
||
}
|
||
break;
|
||
case EParameterType.ByteArray:
|
||
{
|
||
if (dValue != "" && dValue.Length != 4) result.AppendLine($"【{owner}】的参数【{this.Title}】的“默认值”【 {dValue} 】应该是“0x”引导的{4}位16进制数,例如“0xAAFF00”!");
|
||
if (eValue != "" && ((eValue.Length % 2) != 0)) result.AppendLine($"【{owner}】的参数【{this.Title}】的“设置值”【 {eValue} 】应该是“0x”偶数个16进制数,例如“0xAAFF00”!");
|
||
}
|
||
break;
|
||
default: break;
|
||
}
|
||
}
|
||
break;
|
||
}
|
||
string strBuffer = result.ToString();
|
||
return string.IsNullOrEmpty(strBuffer) ? null : strBuffer;
|
||
}
|
||
/// <summary>
|
||
/// 为一个使用子符串表示的变量变值;注意:不能使用引用表达式,[""]与[null]会返回参数的默认值或C#语言的“类型”默认值!
|
||
/// </summary>
|
||
/// <param name="sValue">用字符串表示的变量</param>
|
||
/// <param name="value">如果成功则存储变量的值</param>
|
||
/// <returns>如果失败则返回失败原因,成功则返回“null”</returns>
|
||
public string Evaluate(string sValue, out object value)
|
||
{
|
||
EParameterType type = this.Type;
|
||
sValue = string.IsNullOrWhiteSpace(sValue) ? (string.IsNullOrWhiteSpace(this.Default) ? "" : this.Default) : sValue;
|
||
|
||
if (sValue.StartsWith(FutureInstruct.PR_StartString))
|
||
{
|
||
value = null;
|
||
return $"请先从上下文中获取引用表达式【{sValue}】的值表式再进行求值操作!";
|
||
}
|
||
|
||
string typeName = type.GetParameterTypeName();
|
||
string ownerName = ((this.AttachObject as IConfigurableObject)?.Title) ?? "???";
|
||
|
||
bool sign = true;
|
||
object result = null;
|
||
StringBuilder strBuilder = new StringBuilder();
|
||
|
||
//根据不同的参数类型进行不同的求值逻辑;
|
||
switch (type)
|
||
{
|
||
case EParameterType.Boolean:
|
||
{
|
||
bool oValue = false;
|
||
sign = bool.TryParse(sValue, out oValue);
|
||
result = oValue;
|
||
}
|
||
break;
|
||
case EParameterType.DateTime:
|
||
{
|
||
DateTime oValue = DateTime.Now;
|
||
sign = DateTime.TryParse(sValue, out oValue);
|
||
result = oValue;
|
||
}
|
||
break;
|
||
case EParameterType.Enums:
|
||
{
|
||
int oValue = 0;
|
||
sign = int.TryParse(sValue, out oValue);
|
||
result = oValue;
|
||
}
|
||
break;//需要检查候选值
|
||
case EParameterType.Integer:
|
||
{
|
||
int oValue = 0;
|
||
sign = int.TryParse(sValue, out oValue);
|
||
result = oValue;
|
||
}
|
||
break;//需要检查候选值
|
||
case EParameterType.Number:
|
||
{
|
||
double oValue = 0;
|
||
sign = double.TryParse(sValue, out oValue);
|
||
result = oValue;
|
||
}
|
||
break;//需要检查候选值
|
||
case EParameterType.String: { result = sValue; } break;//需要检查候选值
|
||
case EParameterType.RichText: { result = sValue; } break;
|
||
case EParameterType.Variant: { result = sValue; } break;
|
||
case EParameterType.IntArray:
|
||
{
|
||
if (sValue == "") result = new List<int>();
|
||
else
|
||
{
|
||
try { result = sValue.Decode4Json<List<int>>(); }
|
||
catch { sign = false; result = null; }
|
||
}
|
||
}
|
||
break;
|
||
case EParameterType.NumArray:
|
||
{
|
||
if (sValue == "") result = new List<double>();
|
||
else
|
||
{
|
||
try { result = sValue.Decode4Json<List<double>>(); }
|
||
catch { sign = false; result = null; }
|
||
}
|
||
}
|
||
break;
|
||
case EParameterType.TxtArray:
|
||
{
|
||
if (sValue == "") result = new List<string>();
|
||
else
|
||
{
|
||
try { result = sValue.Decode4Json<List<string>>(); }
|
||
catch { sign = false; result = null; }
|
||
}
|
||
}
|
||
break;
|
||
case EParameterType.ValArray:
|
||
{
|
||
if (sValue == "") result = new List<object>();
|
||
else
|
||
{
|
||
try { result = sValue.Decode4Json<List<object>>(); }
|
||
catch { sign = false; result = null; }
|
||
}
|
||
}
|
||
break;//需要检查候选值
|
||
default://所有不同长度的字节码类型
|
||
{
|
||
string hxValue = sValue ?? "";
|
||
hxValue = hxValue.Trim().ToUpper();
|
||
if (hxValue.Length > 1 && hxValue.StartsWith("0X")) hxValue = hxValue.Substring(2);
|
||
|
||
foreach (char c in hxValue)
|
||
{
|
||
if (c < 48 || c > 70 || (c > 57 && c < 65))
|
||
{
|
||
sign = false;
|
||
break;
|
||
}
|
||
}
|
||
if (!sign) result = null;
|
||
else
|
||
{
|
||
switch (this.Type)
|
||
{
|
||
case EParameterType.Byte:
|
||
{
|
||
if (hxValue.Length < 2) hxValue.PadLeft(2, '0');
|
||
else hxValue = hxValue.Substring(hxValue.Length - 2);
|
||
}
|
||
break;
|
||
case EParameterType.Word:
|
||
{
|
||
if (hxValue.Length < 4) hxValue.PadLeft(4, '0');
|
||
else hxValue = hxValue.Substring(hxValue.Length - 4);
|
||
}
|
||
break;
|
||
case EParameterType.DWord:
|
||
{
|
||
if (hxValue.Length < 8) hxValue.PadLeft(8, '0');
|
||
else hxValue = hxValue.Substring(hxValue.Length - 8);
|
||
}
|
||
break;
|
||
case EParameterType.LWord:
|
||
{
|
||
if (hxValue.Length < 16) hxValue.PadLeft(16, '0');
|
||
else hxValue = hxValue.Substring(hxValue.Length - 16);
|
||
}
|
||
break;
|
||
case EParameterType.ByteArray:
|
||
{
|
||
if ((hxValue.Length % 2) != 0) hxValue = $"0{hxValue}";
|
||
}
|
||
break;
|
||
default: break;
|
||
}
|
||
byte[] bytes = new byte[hxValue.Length / 2];
|
||
for (int i = 0; i < bytes.Length; i++)
|
||
{
|
||
string vhx = hxValue.Substring(i * 2, 2);
|
||
bytes[i] = Convert.ToByte(vhx, 16);
|
||
}
|
||
result = bytes;
|
||
}
|
||
}
|
||
break;
|
||
}
|
||
|
||
value = result;
|
||
if (sign) return null;
|
||
else
|
||
{
|
||
string strBuffer = strBuilder.ToString();
|
||
return string.IsNullOrEmpty(strBuffer) ? null : strBuffer;
|
||
}
|
||
}
|
||
/// <summary>
|
||
/// 获取当前变量的默认值;请使用可空类型接收
|
||
/// </summary>
|
||
/// <returns>如果未设置则返回该类型的缺省值,如果设置错误则返回null</returns>
|
||
public object GetDefault()
|
||
{
|
||
EParameterType type = this.Type;
|
||
string sValue = this.Default ?? "";
|
||
|
||
switch (type)
|
||
{
|
||
case EParameterType.Boolean:
|
||
{
|
||
if (sValue == "") return false;
|
||
bool result = false;
|
||
bool sign = bool.TryParse(sValue, out result);
|
||
if (sign) return result;
|
||
else return null;
|
||
}
|
||
case EParameterType.DateTime:
|
||
{
|
||
if (sValue == "") return DateTime.Now;
|
||
DateTime result = DateTime.Now;
|
||
bool sign = DateTime.TryParse(sValue, out result);
|
||
if (sign) return result;
|
||
else return null;
|
||
}
|
||
case EParameterType.Enums: //本质上是Int
|
||
{
|
||
if (sValue == "") return default(EParameterType);
|
||
int result = 0;
|
||
bool sign = int.TryParse(sValue, out result);
|
||
if (sign) return result;
|
||
else return null;
|
||
}
|
||
case EParameterType.Integer:
|
||
{
|
||
if (sValue == "") return default(EParameterType);
|
||
int result = 0;
|
||
bool sign = int.TryParse(sValue, out result);
|
||
if (sign) return result;
|
||
else return null;
|
||
}
|
||
case EParameterType.Number:
|
||
{
|
||
if (sValue == "") return default(EParameterType);
|
||
double result = 0;
|
||
bool sign = double.TryParse(sValue, out result);
|
||
if (sign) return result;
|
||
else return null;
|
||
}
|
||
case EParameterType.String: return sValue;
|
||
case EParameterType.RichText: return sValue;
|
||
case EParameterType.Variant: return sValue;
|
||
case EParameterType.IntArray:
|
||
{
|
||
if (sValue == "") return new List<string>();
|
||
else
|
||
{
|
||
try { return sValue.Decode4Json<List<int>>(); }
|
||
catch { return null; }
|
||
}
|
||
}
|
||
case EParameterType.NumArray:
|
||
{
|
||
if (sValue == "") return new List<string>();
|
||
else
|
||
{
|
||
try { return sValue.Decode4Json<List<double>>(); }
|
||
catch { return null; }
|
||
}
|
||
}
|
||
case EParameterType.TxtArray:
|
||
{
|
||
if (sValue == "") return new List<string>();
|
||
else
|
||
{
|
||
try { return sValue.Decode4Json<List<string>>(); }
|
||
catch { return null; }
|
||
}
|
||
}
|
||
case EParameterType.ValArray:
|
||
{
|
||
if (sValue == "") return new List<object>();
|
||
else
|
||
{
|
||
try { return sValue.Decode4Json<List<object>>(); }
|
||
catch { return null; }
|
||
}
|
||
}
|
||
default:
|
||
{
|
||
string hxValue = sValue ?? "";
|
||
hxValue = hxValue.Trim().ToUpper();
|
||
if (hxValue.Length > 1 && hxValue.StartsWith("0X")) hxValue = hxValue.Substring(2);
|
||
|
||
bool sign = true;
|
||
foreach (char c in hxValue)
|
||
{
|
||
if (c < 48 || c > 70 || (c > 57 && c < 65))
|
||
{
|
||
sign = false;
|
||
break;
|
||
}
|
||
}
|
||
//如果不是有效的16进制字符串则直接返回null
|
||
if (!sign) return null;
|
||
else
|
||
{
|
||
switch (type)
|
||
{
|
||
case EParameterType.Byte:
|
||
{
|
||
if (hxValue.Length < 2) hxValue.PadLeft(2, '0');
|
||
else hxValue = hxValue.Substring(hxValue.Length - 2);
|
||
}
|
||
break;
|
||
case EParameterType.Word:
|
||
{
|
||
if (hxValue.Length < 4) hxValue.PadLeft(4, '0');
|
||
else hxValue = hxValue.Substring(hxValue.Length - 4);
|
||
}
|
||
break;
|
||
case EParameterType.DWord:
|
||
{
|
||
if (hxValue.Length < 8) hxValue.PadLeft(8, '0');
|
||
else hxValue = hxValue.Substring(hxValue.Length - 8);
|
||
}
|
||
break;
|
||
case EParameterType.LWord:
|
||
{
|
||
if (hxValue.Length < 16) hxValue.PadLeft(16, '0');
|
||
else hxValue = hxValue.Substring(hxValue.Length - 16);
|
||
}
|
||
break;
|
||
case EParameterType.ByteArray:
|
||
{
|
||
if ((hxValue.Length % 2) != 0) hxValue = $"0{hxValue}";
|
||
}
|
||
break;
|
||
default: break;
|
||
}
|
||
byte[] bytes = new byte[hxValue.Length / 2];
|
||
for (int i = 0; i < bytes.Length; i++)
|
||
{
|
||
string vhx = hxValue.Substring(i * 2, 2);
|
||
bytes[i] = Convert.ToByte(vhx, 16);
|
||
}
|
||
return bytes;
|
||
}
|
||
}
|
||
}
|
||
}
|
||
}
|
||
}
|