chr
2026-04-05 fe750b791d5b517cc4e9bc8e99a9a75139a0cfba
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
using System;
using System.Collections.Generic;
using System.Linq;
using System.Xml.Serialization;
 
namespace OpenTap.Plugins.BasicSteps
{
    public class SweepParam
    {
        internal SweepLoop Step;
        public string Name => Member?.Name;
 
        object[] _values = Array.Empty<object>();
        public object[] Values { get => _values; set => _values = value; }
 
        object _defaultValue;
        [XmlIgnore]
        public object DefaultValue
        {
            get => cloneObject(_defaultValue);
            set => _defaultValue = value;
        }
 
        [XmlIgnore]
        public ITypeData Type => Member?.TypeDescriptor; 
 
        public string[] MemberNames { get; set; }
 
        internal static string GetMemberName(IMemberData member) => member.DeclaringType.Name + "." + member.Name;
        
 
        IMemberData[] members = Array.Empty<IMemberData>();
        [XmlIgnore]
        public IMemberData[] Members
        {
            get => members;
            set
            {
                members = value;
                MemberNames = value.Select(GetMemberName).ToArray();
                Step?.parametersChanged();
            }
        }
        
        /// <summary>
        /// The property from where attributes are pulled.
        /// </summary>
        
        public IMemberData Member => Members?.FirstOrDefault();
 
        /// <summary>
        /// Default constructor. Used by serializer.
        /// </summary>
        public SweepParam()
        {
        }
 
        /// <summary>
        /// Initializes a new instance of the SweepParam class. For use when programatically creating a <see cref="SweepLoop"/>
        /// </summary>
        /// <param name="props">Property to sweep. This should be one of the properties on one of the childsteps of the <see cref="SweepLoop"/>.</param>
        public SweepParam(IEnumerable<IMemberData> props) : this()
        {
            Members = props.Distinct().ToArray();
            if (Members.Length == 0)
                throw new ArgumentException("Must contain at least one member", nameof(props));
 
            if (!Members.All(p => Equals(p.TypeDescriptor, Type)))
                throw new ArgumentException("All members must be of the same type", nameof(props));
        }
 
        public SweepParam(IEnumerable<IMemberData> members, params object[] values):this(members)
        {
            Resize(values.Length);
            for(int i = 0; i < values.Length; i++)
            {
                Values[i] = values[i];
            }
        }
 
        public override string ToString()
        {
            return string.Format("{0} : {1}", Name, Type.Name);
        }
 
        TapSerializer serializer = null;
        object cloneObject(object newValue)
        {
            if (newValue == null) return null;
            if (StringConvertProvider.TryGetString(newValue, out string str))
            {
                if (StringConvertProvider.TryFromString(str, TypeData.GetTypeData(newValue), this.Step, out object result))
                {
                    newValue = result;
                }
            }
            else
            {
 
                string serialized = null;
 
                serializer = new TapSerializer();
                try
                {
 
                    serialized = serializer.SerializeToString(newValue);
                    newValue = serializer.DeserializeFromString(serialized, TypeData.GetTypeData(newValue));
                }
                catch
                {
 
                }
 
            }
            return newValue;
        }
        public void Resize(int newCount)
        {
            int oldCount = Values.Length;
            if (oldCount == newCount)
                return;
 
            var oldValues = Values;
            Array.Resize(ref _values, newCount);
            for (int i = oldCount; i < newCount; i++)
            {
                object newValue = null; 
                if (i == 0)
                    newValue = DefaultValue;
                else
                    newValue = _values.GetValue(i - 1);
                newValue = cloneObject(newValue);
                _values.SetValue(newValue, i);
            }
            var copyAmount = Math.Min(newCount, oldValues.Length);
            Array.Copy(oldValues, Values, copyAmount);
            Step?.parametersChanged();
        }
    }
}