using OpenTap.Addin.Entity;
|
using System;
|
using System.Collections.Concurrent;
|
using System.Collections.Generic;
|
using System.Dynamic;
|
|
namespace OpenTap.Addin
|
{
|
public class RuntimeVariable : DynamicObject
|
{
|
public string __name___ { get; set; }
|
|
public dynamic __data___ { get; set; }
|
|
private TestPlanRun __planRun___;
|
|
public override bool Equals(object obj)
|
{
|
if (obj is RuntimeVariable ev)
|
{
|
return ev.__name___ == __name___ && ev.__data___ == __data___;
|
}
|
return base.Equals(obj);
|
}
|
|
public override string ToString()
|
{
|
return __data___?.ToString();
|
}
|
|
public override int GetHashCode()
|
{
|
var h1 = __name___?.GetHashCode() ?? 0;
|
var h2 = __data___?.GetHashCode() ?? 0;
|
return (((h1 + 742759321) * 1593213024) + h2) * 1079741372;
|
}
|
|
public RuntimeVariable(TestPlanRun run, string name, dynamic variables)
|
{
|
__planRun___ = run;
|
__name___ = name;
|
__data___ = variables;
|
}
|
|
public dynamic this[int index]
|
{
|
get
|
{
|
return __data___[index];
|
}
|
set
|
{
|
//__data___[index] = value;
|
|
//if (value is RuntimeVariable rv)
|
//{
|
// __data___[index] = value;
|
//}
|
//else
|
//{
|
// __data___[index] = new RuntimeVariable(__planRun___, null, value);
|
//}
|
|
if (value is RuntimeVariable rv)
|
{
|
__data___[index] = rv.__data___;
|
}
|
else
|
{
|
__data___[index] = value;
|
}
|
}
|
}
|
|
public dynamic this[RuntimeVariable irv]
|
{
|
get
|
{
|
return __data___[irv.__data___];
|
}
|
set
|
{
|
//if (value is RuntimeVariable rv)
|
//{
|
// __data___[irv.__data___] = rv;
|
//}
|
//else
|
//{
|
// __data___[irv.__data___] = new RuntimeVariable(__planRun___, null, value);
|
//}
|
|
if (value is RuntimeVariable rv)
|
{
|
__data___[irv.__data___] = rv.__data___;
|
}
|
else
|
{
|
__data___[irv.__data___] = value;
|
}
|
}
|
}
|
|
public override bool TryGetMember(GetMemberBinder binder, out dynamic result)
|
{
|
result = null;
|
string name = binder.Name;
|
if (__data___ is ConcurrentDictionary<string, RuntimeVariable> vs)
|
{
|
if (vs.TryGetValue(name, out var variable))
|
{
|
result = variable;//.data;
|
return true;
|
}
|
result = new NullVariable($"{this.__name___}.{name}");
|
return true;
|
}
|
|
var pInfo = __data___.GetType().GetProperty(name);
|
if (pInfo == null)
|
{
|
return false;
|
}
|
result = pInfo.GetValue(__data___);
|
return true;
|
}
|
|
public override bool TrySetMember(SetMemberBinder binder, object value)
|
{
|
string name = binder.Name;
|
|
if (__data___ is ConcurrentDictionary<string, RuntimeVariable> vs)
|
{
|
if (vs.TryGetValue(name, out var variable))
|
{
|
if (value is RuntimeVariable rv)
|
{
|
// 引用传递
|
vs[name] = rv;
|
}
|
else
|
{
|
variable.__data___ = NumberData.Format(value);
|
}
|
return true;
|
}
|
else
|
{
|
if (value is RuntimeVariable rv)
|
{
|
// 引用传递
|
vs[name] = rv;
|
}
|
else
|
{
|
var v = new RuntimeVariable(__planRun___, name, NumberData.Format(value));
|
vs[name] = v;
|
}
|
return true;
|
}
|
}
|
var pInfo = __data___.GetType().GetProperty(name);
|
if (pInfo == null)
|
{
|
return false;
|
}
|
pInfo.SetValue(__data___, value);
|
return true;
|
}
|
|
public static dynamic operator +(RuntimeVariable left, dynamic right)
|
{
|
if (right is RuntimeVariable rrv)
|
{
|
right = rrv.__data___;
|
}
|
return left.__data___ + right;
|
}
|
|
public static dynamic operator -(RuntimeVariable left, dynamic right)
|
{
|
if (right is RuntimeVariable rrv)
|
{
|
right = rrv.__data___;
|
}
|
return left.__data___ - right;
|
}
|
|
public static dynamic operator *(RuntimeVariable left, dynamic right)
|
{
|
if (right is RuntimeVariable rrv)
|
{
|
right = rrv.__data___;
|
}
|
return left.__data___ * right;
|
}
|
|
public static dynamic operator /(RuntimeVariable left, dynamic right)
|
{
|
if (right is RuntimeVariable rrv)
|
{
|
right = rrv.__data___;
|
}
|
return left.__data___ / right;
|
}
|
|
public static dynamic operator %(RuntimeVariable left, dynamic right)
|
{
|
if (right is RuntimeVariable rrv)
|
{
|
right = rrv.__data___;
|
}
|
return left.__data___ % right;
|
}
|
|
public static bool operator >(RuntimeVariable left, dynamic right)
|
{
|
if (right is RuntimeVariable rv)
|
{
|
right = rv.__data___;
|
}
|
return left.__data___ > right;
|
}
|
|
public static bool operator <(RuntimeVariable left, dynamic right)
|
{
|
if (right is RuntimeVariable rv)
|
{
|
right = rv.__data___;
|
}
|
return left.__data___ < right;
|
}
|
|
public static bool operator >=(RuntimeVariable left, dynamic right)
|
{
|
if (right is RuntimeVariable rv)
|
{
|
right = rv.__data___;
|
}
|
return left.__data___ >= right;
|
}
|
|
public static bool operator <=(RuntimeVariable left, dynamic right)
|
{
|
if (right is RuntimeVariable rv)
|
{
|
right = rv.__data___;
|
}
|
return left.__data___ <= right;
|
}
|
public static bool operator ==(RuntimeVariable left, dynamic right)
|
{
|
if (right is RuntimeVariable rrv)
|
{
|
right = rrv.__data___;
|
}
|
return left.__data___ == right;
|
}
|
|
public static bool operator ==(NumberData left, RuntimeVariable right)
|
{
|
return left == right.__data___;
|
}
|
|
public static bool operator !=(NumberData left, RuntimeVariable right)
|
{
|
return left != right.__data___;
|
}
|
|
public static bool operator >(NumberData left, RuntimeVariable right)
|
{
|
return left > right.__data___;
|
}
|
|
public static bool operator >=(NumberData left, RuntimeVariable right)
|
{
|
return left >= right.__data___;
|
}
|
|
public static bool operator <(NumberData left, RuntimeVariable right)
|
{
|
return left < right.__data___;
|
}
|
|
public static bool operator <=(NumberData left, RuntimeVariable right)
|
{
|
return left <= right.__data___;
|
}
|
|
|
public static bool operator ==(RuntimeVariable left, NumberData right)
|
{
|
return left.__data___ == right;
|
}
|
|
public static bool operator !=(RuntimeVariable left, NumberData right)
|
{
|
return left.__data___ != right;
|
}
|
|
public static bool operator >(RuntimeVariable left, NumberData right)
|
{
|
return left.__data___ > right;
|
}
|
|
public static bool operator >=(RuntimeVariable left, NumberData right)
|
{
|
return left.__data___ >= right;
|
}
|
|
public static bool operator <(RuntimeVariable left, NumberData right)
|
{
|
return left.__data___ < right;
|
}
|
|
public static bool operator <=(RuntimeVariable left, NumberData right)
|
{
|
return left.__data___ <= right;
|
}
|
|
public static bool operator !=(RuntimeVariable left, dynamic right)
|
{
|
if (right is RuntimeVariable rrv)
|
{
|
right = rrv.__data___;
|
}
|
return left.__data___ != right;
|
}
|
|
|
public static implicit operator bool(RuntimeVariable obj)
|
{
|
return (bool)obj.__data___;
|
}
|
|
public static bool ToBool(RuntimeVariable obj)
|
{
|
return (bool)obj.__data___;
|
}
|
|
public static implicit operator RuntimeVariable(bool obj)
|
{
|
return new RuntimeVariable(null, null, obj);
|
}
|
|
public static bool operator true(RuntimeVariable obj)
|
{
|
return (bool)obj.__data___;
|
}
|
|
public static bool operator false(RuntimeVariable obj)
|
{
|
return (bool)!obj.__data___;
|
}
|
|
public static RuntimeVariable operator !(RuntimeVariable obj)
|
{
|
return new RuntimeVariable(obj.__planRun___, null, !obj.__data___);
|
}
|
|
public static RuntimeVariable operator |(RuntimeVariable left, RuntimeVariable right)
|
{
|
return new RuntimeVariable(null, null, left.__data___ | right.__data___);
|
}
|
|
public static RuntimeVariable operator &(RuntimeVariable left, RuntimeVariable right)
|
{
|
return new RuntimeVariable(null, null, left.__data___ & right.__data___);
|
}
|
|
|
public static dynamic operator +(dynamic left, RuntimeVariable right)
|
{
|
if (left is RuntimeVariable lrv)
|
{
|
left = lrv.__data___;
|
}
|
return left + right.__data___;
|
}
|
|
public static dynamic operator -(dynamic left, RuntimeVariable right)
|
{
|
if (left is RuntimeVariable lrv)
|
{
|
left = lrv.__data___;
|
}
|
return left - right.__data___;
|
}
|
|
public static dynamic operator *(dynamic left, RuntimeVariable right)
|
{
|
if (left is RuntimeVariable lrv)
|
{
|
left = lrv.__data___;
|
}
|
return left * right.__data___;
|
}
|
|
public static dynamic operator /(dynamic left, RuntimeVariable right)
|
{
|
if (left is RuntimeVariable lrv)
|
{
|
left = lrv.__data___;
|
}
|
return left / right.__data___;
|
}
|
|
public static dynamic operator %(dynamic left, RuntimeVariable right)
|
{
|
if (left is RuntimeVariable lrv)
|
{
|
left = lrv.__data___;
|
}
|
return left % right.__data___;
|
}
|
|
public static bool operator >(dynamic left, RuntimeVariable right)
|
{
|
if (left is RuntimeVariable rv)
|
{
|
left = rv.__data___;
|
}
|
return left > right.__data___;
|
}
|
|
public static bool operator <(dynamic left, RuntimeVariable right)
|
{
|
if (left is RuntimeVariable rv)
|
{
|
left = rv.__data___;
|
}
|
return left < right.__data___;
|
}
|
|
public static bool operator >=(dynamic left, RuntimeVariable right)
|
{
|
if (left is RuntimeVariable rv)
|
{
|
left = rv.__data___;
|
}
|
return left >= right.__data___;
|
}
|
|
public static bool operator <=(dynamic left, RuntimeVariable right)
|
{
|
if (left is RuntimeVariable rv)
|
{
|
left = rv.__data___;
|
}
|
return left <= right.__data___;
|
}
|
|
public static bool operator ==(dynamic left, RuntimeVariable right)
|
{
|
if (left is RuntimeVariable lrv)
|
{
|
left = lrv.__data___;
|
}
|
return left == right.__data___;
|
}
|
|
public static bool operator !=(dynamic left, RuntimeVariable right)
|
{
|
if (left is RuntimeVariable lrv)
|
{
|
left = lrv.__data___;
|
}
|
return left != right.__data___;
|
}
|
|
public static RuntimeVariable FromTestVariables(TestPlanRun run, string name, IEnumerable<TestVariable> variables)
|
{
|
var runtimeVariablePool = new ConcurrentDictionary<string, RuntimeVariable>();
|
foreach (var data in variables)
|
{
|
RuntimeVariable runTime = data.ToRuntime(run);
|
if (runTime is null) continue;
|
runtimeVariablePool[runTime.__name___] = runTime;
|
}
|
return new RuntimeVariable(run, name, runtimeVariablePool);
|
}
|
}
|
}
|