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 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 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 variables) { var runtimeVariablePool = new ConcurrentDictionary(); 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); } } }