using OpenTap.Addin.Annotation;
|
using OpenTap.Addin.Entity;
|
using System;
|
using System.Collections.Concurrent;
|
using System.Collections.ObjectModel;
|
using System.ComponentModel;
|
using System.Dynamic;
|
using System.Linq;
|
using System.Runtime.CompilerServices;
|
using System.Xml.Serialization;
|
|
namespace OpenTap.Addin
|
{
|
public enum TestVariableType
|
{
|
String = 0,
|
Int = 1,
|
Double = 2,
|
Bool = 3,
|
Container = 8,
|
Refrence = 9
|
}
|
|
public class NullVariable : DynamicObject
|
{
|
private string _____name_____;
|
|
public NullVariable(string name)
|
{
|
_____name_____ = name;
|
}
|
|
public override bool TryGetMember(GetMemberBinder binder, out object result)
|
{
|
throw new ArgumentException($"参数 {_____name_____} 不存在");
|
}
|
|
public override bool TrySetMember(SetMemberBinder binder, object value)
|
{
|
throw new ArgumentException($"参数 {_____name_____} 不存在");
|
}
|
|
public object this[int index]
|
{
|
get
|
{
|
throw new ArgumentException($"参数 {_____name_____} 不存在");
|
}
|
set
|
{
|
throw new ArgumentException($"参数 {_____name_____} 不存在");
|
}
|
}
|
|
public static bool operator ==(NullVariable v1, object v2)
|
{
|
if (v2 is NullVariable) return true;
|
return v2 == null;
|
}
|
|
public static bool operator !=(NullVariable v1, object v2)
|
{
|
if (v2 is NullVariable vv2) return v1 == vv2;
|
return v2 != null;
|
}
|
|
public override string ToString()
|
{
|
return "NULL";
|
}
|
|
public override bool Equals(object obj)
|
{
|
return obj is NullVariable variable;
|
}
|
|
public override int GetHashCode()
|
{
|
throw new NullReferenceException();
|
}
|
}
|
|
|
public class TestVariable : DynamicObject, INotifyPropertyChanged
|
{
|
#region ...
|
public event PropertyChangedEventHandler PropertyChanged;
|
|
protected void Set([CallerMemberName] string name = null)
|
{
|
|
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(name));
|
}
|
|
protected void Set<T>(ref T old, T @new, [CallerMemberName] string propertyName = null)
|
{
|
old = @new;
|
if (propertyName != null)
|
{
|
Set(propertyName);
|
}
|
}
|
#endregion
|
|
private bool nameCanEdit = true;
|
[XmlIgnore]
|
public bool NameCanEdit
|
{
|
get => nameCanEdit;
|
set
|
{
|
Set(ref nameCanEdit, value);
|
}
|
}
|
|
private string name;
|
[DataGridCol("名称", "*", true)]
|
public string Name
|
{
|
get => name;
|
set
|
{
|
Set(ref name, value);
|
Set(nameof(Title));
|
}
|
}
|
|
private string contextName;
|
[XmlIgnore]
|
public string ContextName
|
{
|
get => contextName;
|
set
|
{
|
Set(ref contextName, value);
|
Set(nameof(Title));
|
}
|
}
|
|
[XmlIgnore]
|
public string Title
|
{
|
get
|
{
|
if (string.IsNullOrEmpty(ContextName))
|
return Name;
|
return $"{Name} ({ContextName})";
|
}
|
set
|
{
|
Set(ref name, value);
|
Set(nameof(Title));
|
}
|
}
|
|
public bool IsArray { get; set; }
|
|
private TestVariableType type;
|
[DataGridCol("类型", "*", true)]
|
|
public TestVariableType Type
|
{
|
get => type;
|
set
|
{
|
Set(ref type, value);
|
}
|
}
|
|
[DataGridCol("值", "*", false, true)]
|
public string Value { get; set; }
|
|
private ObservableCollection<TestVariable> children = new ObservableCollection<TestVariable>();
|
public ObservableCollection<TestVariable> Children
|
{
|
get => children;
|
set
|
{
|
Set(ref children, value);
|
}
|
}
|
|
public override bool TryGetMember(GetMemberBinder binder, out object result)
|
{
|
result = null;
|
string name = binder.Name;
|
var pInfo = typeof(TestVariable).GetProperty(name);
|
if (pInfo == null)
|
{
|
var child = Children.FirstOrDefault(c => c.Name == name);
|
if (child == null)
|
{
|
result = new NullVariable($"{this.Name}.{name}");
|
return true;
|
}
|
if (child.IsArray || child.Type == TestVariableType.Container)
|
{
|
result = child;
|
}
|
else
|
{
|
result = child.GetValue();
|
}
|
return true;
|
}
|
else
|
{
|
result = pInfo.GetValue(this);
|
return true;
|
}
|
}
|
|
public object this[int index]
|
{
|
get
|
{
|
if (!IsArray)
|
{
|
throw new Exception();
|
}
|
return Children[index].GetValue();
|
}
|
set
|
{
|
if (!IsArray)
|
{
|
throw new Exception();
|
}
|
Children[index].Value = value.ToString();
|
}
|
}
|
|
public override bool TrySetMember(SetMemberBinder binder, object value)
|
{
|
string name = binder.Name;
|
var pInfo = typeof(TestVariable).GetProperty(name);
|
if (pInfo == null)
|
{
|
var child = Children.FirstOrDefault(c => c.Name == name);
|
if (child == null)
|
{
|
if (Type != TestVariableType.Container)
|
{
|
return false;
|
}
|
child = new TestVariable
|
{
|
Name = name
|
};
|
Children.Add(child);
|
}
|
|
child.Type = FormatType(value.GetType());
|
child.Value = value.ToString();
|
return true;
|
}
|
else
|
{
|
pInfo.SetValue(this, value);
|
return true;
|
}
|
}
|
|
public object GetValue()
|
{
|
if (Type == TestVariableType.Int)
|
{
|
return new NumberData(Value);
|
}
|
else if (Type == TestVariableType.Double)
|
{
|
return new NumberData(Value);
|
}
|
else if (Type == TestVariableType.Bool)
|
{
|
if (bool.TryParse(Value, out bool boolValue))
|
return boolValue;
|
}
|
else if (Type == TestVariableType.String)
|
{
|
return Value;
|
}
|
return null;
|
}
|
|
|
public RuntimeVariable ToRuntime(TestPlanRun run)
|
{
|
if (IsArray)
|
{
|
switch (Type)
|
{
|
case TestVariableType.String:
|
return new RuntimeVariable(run, Name, Children.Select(e => e.GetValue()).ToArray());
|
case TestVariableType.Int:
|
return new RuntimeVariable(run, Name, Children.Select(e => e.GetValue()).ToArray());
|
case TestVariableType.Double:
|
return new RuntimeVariable(run, Name, Children.Select(e => e.GetValue()).ToArray());
|
case TestVariableType.Bool:
|
return new RuntimeVariable(run, Name, Children.Select(e => e.GetValue()).ToArray());
|
case TestVariableType.Container:
|
return new RuntimeVariable(run, Name, Children.Select(e => e.ToRuntime(run)).ToArray());
|
case TestVariableType.Refrence:
|
return new RuntimeVariable(run, Name, Children.Select(e => e.GetValue()).ToArray());
|
}
|
}
|
else
|
{
|
switch (Type)
|
{
|
case TestVariableType.String:
|
return new RuntimeVariable(run, Name, Value);
|
case TestVariableType.Int:
|
return new RuntimeVariable(run, Name, GetValue());
|
case TestVariableType.Double:
|
return new RuntimeVariable(run, Name, GetValue());
|
case TestVariableType.Bool:
|
return new RuntimeVariable(run, Name, GetValue());
|
case TestVariableType.Container:
|
return new RuntimeVariable(run, Name, new ConcurrentDictionary<string, RuntimeVariable>
|
(Children.Select(e => e.ToRuntime(run)).ToDictionary(v => v.__name___, v => v)));
|
case TestVariableType.Refrence:
|
return new RuntimeVariable(run, Name, null);
|
}
|
}
|
return null;
|
}
|
|
public object GetValue__()
|
{
|
if (Type == TestVariableType.Int)
|
{
|
if (int.TryParse(Value, out int intValue))
|
return intValue;
|
}
|
else if (Type == TestVariableType.Double)
|
{
|
if (double.TryParse(Value, out double doubleValue))
|
return doubleValue;
|
}
|
else if (Type == TestVariableType.Bool)
|
{
|
if (bool.TryParse(Value, out bool boolValue))
|
return boolValue;
|
}
|
else if (Type == TestVariableType.String)
|
{
|
return Value;
|
}
|
return null;
|
}
|
|
//public RuntimeVariable ToRuntime___()
|
//{
|
// if (IsArray)
|
// {
|
// switch (Type)
|
// {
|
// case TestVariableType.String:
|
// return new RuntimeVariable
|
// {
|
// Name = Name,
|
// Type = typeof(string[]),
|
// TypeName = "string[]",
|
// data = Children.Select(e => e.GetValue()).ToArray()
|
// };
|
// case TestVariableType.Int:
|
// return new RuntimeVariable
|
// {
|
// Name = Name,
|
// Type = typeof(int[]),
|
// TypeName = "int[]",
|
// data = Children.Select(e => e.GetValue()).ToArray()
|
// };
|
// case TestVariableType.Double:
|
// return new RuntimeVariable
|
// {
|
// Name = Name,
|
// Type = typeof(double[]),
|
// TypeName = "double[]",
|
// data = Children.Select(e => e.GetValue()).ToArray()
|
// };
|
// case TestVariableType.Bool:
|
// return new RuntimeVariable
|
// {
|
// Name = Name,
|
// Type = typeof(bool[]),
|
// TypeName = "bool[]",
|
// data = Children.Select(e => e.GetValue()).ToArray()
|
// };
|
// case TestVariableType.Container:
|
// return new RuntimeVariable
|
// {
|
// Name = Name,
|
// Type = typeof(object[]),
|
// TypeName = "Container[]",
|
// data = new VariableContext(Name, new ConcurrentDictionary<string, RuntimeVariable>
|
// (Children.Select(e => e.ToRuntime()).ToDictionary(v => v.Name, v => v)))
|
// };
|
// }
|
// }
|
// else
|
// {
|
// switch (Type)
|
// {
|
// case TestVariableType.String:
|
// return new RuntimeVariable
|
// {
|
// Name = Name,
|
// Type = typeof(string),
|
// TypeName = "string",
|
// data = Value
|
// };
|
// case TestVariableType.Int:
|
// return new RuntimeVariable
|
// {
|
// Name = Name,
|
// Type = typeof(int),
|
// TypeName = "int",
|
// data = int.Parse(Value)
|
// };
|
// case TestVariableType.Double:
|
// return new RuntimeVariable
|
// {
|
// Name = Name,
|
// Type = typeof(double),
|
// TypeName = "double",
|
// data = double.Parse(Value)
|
// };
|
// case TestVariableType.Bool:
|
// return new RuntimeVariable
|
// {
|
// Name = Name,
|
// Type = typeof(bool),
|
// TypeName = "bool",
|
// data = bool.Parse(Value)
|
// };
|
// case TestVariableType.Container:
|
// return new RuntimeVariable
|
// {
|
// Name = Name,
|
// Type = typeof(object[]),
|
// TypeName = "object",
|
// data = new VariableContext(Name, new ConcurrentDictionary<string, RuntimeVariable>
|
// (Children.Select(e => e.ToRuntime()).ToDictionary(v => v.Name, v => v)))
|
// };
|
// }
|
// }
|
// return null;
|
//}
|
|
//public RuntimeContext ToRuntime2()
|
//{
|
// if (IsArray)
|
// {
|
// var
|
// switch (Type)
|
// {
|
// case TestVariableType.String:
|
// return new RuntimeContext
|
// {
|
// Name = Name,
|
// Type = typeof(string[]),
|
// TypeName = "string[]",
|
// data = Children.Select(e => e.GetValue()).ToArray()
|
// };
|
// case TestVariableType.Int:
|
// return new RuntimeVariable
|
// {
|
// Name = Name,
|
// Type = typeof(int[]),
|
// TypeName = "int[]",
|
// data = Children.Select(e => e.GetValue()).ToArray()
|
// };
|
// case TestVariableType.Double:
|
// return new RuntimeVariable
|
// {
|
// Name = Name,
|
// Type = typeof(double[]),
|
// TypeName = "double[]",
|
// data = Children.Select(e => e.GetValue()).ToArray()
|
// };
|
// case TestVariableType.Bool:
|
// return new RuntimeVariable
|
// {
|
// Name = Name,
|
// Type = typeof(bool[]),
|
// TypeName = "bool[]",
|
// data = Children.Select(e => e.GetValue()).ToArray()
|
// };
|
// case TestVariableType.Container:
|
// return new RuntimeVariable
|
// {
|
// Name = Name,
|
// Type = typeof(object[]),
|
// TypeName = "Container[]",
|
// data = new VariableContext(new ConcurrentDictionary<string, RuntimeVariable>
|
// (Children.Select(e => e.ToRuntime()).ToDictionary(v => v.Name, v => v)))
|
// };
|
// }
|
// }
|
// else
|
// {
|
// switch (Type)
|
// {
|
// case TestVariableType.String:
|
// return new RuntimeVariable
|
// {
|
// Name = Name,
|
// Type = typeof(string),
|
// TypeName = "string",
|
// data = Value
|
// };
|
// case TestVariableType.Int:
|
// return new RuntimeVariable
|
// {
|
// Name = Name,
|
// Type = typeof(int),
|
// TypeName = "int",
|
// data = int.Parse(Value)
|
// };
|
// case TestVariableType.Double:
|
// return new RuntimeVariable
|
// {
|
// Name = Name,
|
// Type = typeof(double),
|
// TypeName = "double",
|
// data = double.Parse(Value)
|
// };
|
// case TestVariableType.Bool:
|
// return new RuntimeVariable
|
// {
|
// Name = Name,
|
// Type = typeof(bool),
|
// TypeName = "bool",
|
// data = bool.Parse(Value)
|
// };
|
// case TestVariableType.Container:
|
// return new RuntimeVariable
|
// {
|
// Name = Name,
|
// Type = typeof(object[]),
|
// TypeName = "object",
|
// data = new VariableContext(new ConcurrentDictionary<string, RuntimeVariable>
|
// (Children.Select(e => e.ToRuntime()).ToDictionary(v => v.Name, v => v)))
|
// };
|
// }
|
// }
|
// return null;
|
//}
|
|
public static TestVariableType FormatType(Type type)
|
{
|
if (type == typeof(string))
|
{
|
return TestVariableType.String;
|
}
|
if (type == typeof(int))
|
{
|
return TestVariableType.Int;
|
}
|
if (type == typeof(double))
|
{
|
return TestVariableType.Double;
|
}
|
if (type == typeof(bool))
|
{
|
return TestVariableType.Bool;
|
}
|
return TestVariableType.Refrence;
|
}
|
|
public static string DefaultValue(TestVariableType type)
|
{
|
switch (type)
|
{
|
case TestVariableType.String:
|
return string.Empty;
|
case TestVariableType.Int:
|
return "0";
|
case TestVariableType.Double:
|
return "0";
|
case TestVariableType.Bool:
|
return "False";
|
default:
|
return null;
|
}
|
}
|
}
|
}
|