对算法输入参数非法情况进行过滤

This commit is contained in:
zhengxuan.zhang
2026-04-20 11:13:40 +08:00
parent 1c6c2ac675
commit e0a7af6226
5 changed files with 208 additions and 24 deletions
@@ -46,6 +46,19 @@ namespace XplorePlane.Services
cancellationToken.ThrowIfCancellationRequested();
var node = enabledNodes[step];
var invalidParameters = node.Parameters
.Where(p => !p.IsValueValid)
.Select(p => p.DisplayName)
.ToList();
if (invalidParameters.Count > 0)
{
throw new PipelineExecutionException(
$"算子 '{node.DisplayName}' 存在无效参数:{string.Join("", invalidParameters)}",
node.Order,
node.OperatorKey);
}
var parameters = node.Parameters
.Where(p => p.IsValueValid)
.ToDictionary(p => p.Name, p => p.Value);
@@ -98,4 +111,4 @@ namespace XplorePlane.Services
return scaled;
}
}
}
}
@@ -1,5 +1,7 @@
using Prism.Mvvm;
using Prism.Mvvm;
using System;
using System.Globalization;
using System.Linq;
using XP.ImageProcessing.Core;
namespace XplorePlane.ViewModels
@@ -16,7 +18,8 @@ namespace XplorePlane.ViewModels
_value = parameter.Value;
MinValue = parameter.MinValue;
MaxValue = parameter.MaxValue;
ParameterType = parameter.ValueType?.Name?.ToLower() switch
Options = parameter.Options;
ParameterType = parameter.ValueType?.Name?.ToLowerInvariant() switch
{
"int32" or "int" => "int",
"double" => "double",
@@ -30,6 +33,7 @@ namespace XplorePlane.ViewModels
public string DisplayName { get; }
public object MinValue { get; }
public object MaxValue { get; }
public string[]? Options { get; }
public string ParameterType { get; }
public bool IsValueValid
@@ -43,29 +47,161 @@ namespace XplorePlane.ViewModels
get => _value;
set
{
if (SetProperty(ref _value, value))
ValidateValue(value);
var normalizedValue = NormalizeValue(value);
if (SetProperty(ref _value, normalizedValue))
ValidateValue(normalizedValue);
}
}
private void ValidateValue(object value)
{
if (value == null || MinValue == null || MaxValue == null)
if (value == null)
{
IsValueValid = true;
IsValueValid = false;
return;
}
try
if (ParameterType == "int")
{
double dVal = Convert.ToDouble(value);
double dMin = Convert.ToDouble(MinValue);
double dMax = Convert.ToDouble(MaxValue);
IsValueValid = dVal >= dMin && dVal <= dMax;
IsValueValid = TryConvertToInt(value, out var intValue) && IsWithinRange(intValue);
return;
}
catch
if (ParameterType == "double")
{
IsValueValid = true; // éžæ•°å€¼ç±»åž‹ä¸åšèŒƒå›´æ ¡éª?
IsValueValid = TryConvertToDouble(value, out var doubleValue) && IsWithinRange(doubleValue);
return;
}
if (ParameterType == "bool")
{
IsValueValid = TryConvertToBool(value, out _);
return;
}
if (Options is { Length: > 0 })
{
var stringValue = Convert.ToString(value, CultureInfo.InvariantCulture) ?? string.Empty;
IsValueValid = Options.Contains(stringValue, StringComparer.OrdinalIgnoreCase);
return;
}
IsValueValid = true;
}
private object NormalizeValue(object value)
{
if (value == null)
return value;
if (ParameterType == "int" && TryConvertToInt(value, out var intValue))
return intValue;
if (ParameterType == "double" && TryConvertToDouble(value, out var doubleValue))
return doubleValue;
if (ParameterType == "bool" && TryConvertToBool(value, out var boolValue))
return boolValue;
return value;
}
private bool IsWithinRange(double value)
{
if (MinValue != null && TryConvertToDouble(MinValue, out var minValue) && value < minValue)
return false;
if (MaxValue != null && TryConvertToDouble(MaxValue, out var maxValue) && value > maxValue)
return false;
return true;
}
private static string NormalizeNumericText(string value)
{
return value.Trim().TrimEnd('、', '', ',', '。', '.', ';', '', ':', '');
}
private static bool TryConvertToInt(object value, out int result)
{
switch (value)
{
case int intValue:
result = intValue;
return true;
case string stringValue:
stringValue = NormalizeNumericText(stringValue);
return int.TryParse(stringValue, NumberStyles.Integer, CultureInfo.InvariantCulture, out result)
|| int.TryParse(stringValue, NumberStyles.Integer, CultureInfo.CurrentCulture, out result);
default:
try
{
result = Convert.ToInt32(value, CultureInfo.InvariantCulture);
return true;
}
catch
{
result = default;
return false;
}
}
}
private static bool TryConvertToDouble(object value, out double result)
{
switch (value)
{
case double doubleValue:
result = doubleValue;
return true;
case float floatValue:
result = floatValue;
return true;
case int intValue:
result = intValue;
return true;
case long longValue:
result = longValue;
return true;
case string stringValue:
stringValue = NormalizeNumericText(stringValue);
return double.TryParse(stringValue, NumberStyles.Float | NumberStyles.AllowThousands, CultureInfo.InvariantCulture, out result)
|| double.TryParse(stringValue, NumberStyles.Float | NumberStyles.AllowThousands, CultureInfo.CurrentCulture, out result);
default:
try
{
result = Convert.ToDouble(value, CultureInfo.InvariantCulture);
return true;
}
catch
{
result = default;
return false;
}
}
}
private static bool TryConvertToBool(object value, out bool result)
{
switch (value)
{
case bool boolValue:
result = boolValue;
return true;
case string stringValue:
return bool.TryParse(stringValue.Trim(), out result);
default:
try
{
result = Convert.ToBoolean(value, CultureInfo.InvariantCulture);
return true;
}
catch
{
result = default;
return false;
}
}
}
}
}
}
+3 -3
View File
@@ -319,7 +319,7 @@
telerik:ScreenTip.Title="模块"
Size="Medium"
SmallImage="/Assets/Icons/Module.png"
Text="模块" />
Text="检测模块" />
<telerik:RadRibbonButton
telerik:ScreenTip.Title="全部保存"
Size="Medium"
@@ -331,12 +331,12 @@
telerik:ScreenTip.Title="消息"
Size="Medium"
SmallImage="/Assets/Icons/message.png"
Text="消息" />
Text="消息弹窗" />
<telerik:RadRibbonButton
telerik:ScreenTip.Title="等待"
Size="Medium"
SmallImage="/Assets/Icons/wait.png"
Text="等待" />
Text="插入等待" />
</StackPanel>
</telerik:RadRibbonGroup>