private static object ParseEnum(string name, string value, Type propertyType) { var obj = StringConvertProvider.FromString(value, TypeData.FromType(propertyType), null, System.Globalization.CultureInfo.InvariantCulture); if (obj == null) { throw new Exception(string.Format("Could not parse argument '{0}'. Argument given: '{1}'. Valid arguments: {2}", name, value, string.Join(", ", propertyType.GetEnumNames()))); } return(obj); }
string validateSweep(decimal Value) { // Mostly copied from Run var props = AvailableParameters.ToArray(); if (props.Length == 0) { return(""); } if (isRunning) { return(""); // Avoid changing the value during run when the gui asks for validation errors. } if (!validateSweepMutex.WaitOne(0)) { return(""); } var originalValues = props.Select(set => set.GetValue(this)).ToArray(); try { var str = StringConvertProvider.GetString(Value, CultureInfo.InvariantCulture); foreach (var set in props) { var val = StringConvertProvider.FromString(str, set.TypeDescriptor, this, CultureInfo.InvariantCulture); set.SetValue(this, val); } return(""); } catch (TargetInvocationException e) { return(e.InnerException.Message); } finally { for (int i = 0; i < props.Length; i++) { props[i].SetValue(this, originalValues[i]); } validateSweepMutex.ReleaseMutex(); } }
public override void Run() { base.Run(); var selected = SelectedMembers.ToArray(); var originalValues = selected.Select(set => set.GetValue(this)).ToArray(); IEnumerable <decimal> range = LinearRange(SweepStart, SweepStop, (int)SweepPoints); if (SweepBehavior == SweepBehavior.Exponential) { range = ExponentialRange(SweepStart, SweepStop, (int)SweepPoints); } var disps = selected.Select(x => x.GetDisplayAttribute()).ToList(); string names = string.Join(", ", disps.Select(x => x.Name)); if (disps.Count > 1) { names = string.Format("{{{0}}}", names); } foreach (var Value in range) { var val = StringConvertProvider.GetString(Value, CultureInfo.InvariantCulture); foreach (var set in selected) { try { var value = StringConvertProvider.FromString(val, set.TypeDescriptor, this, CultureInfo.InvariantCulture); set.SetValue(this, value); } catch (TargetInvocationException ex) { Log.Error("Unable to set '{0}' to value '{2}': {1}", set.GetDisplayAttribute().Name, ex.InnerException.Message, Value); Log.Debug(ex.InnerException); } } // Notify that values might have changes OnPropertyChanged(""); var AdditionalParams = new ResultParameters(); foreach (var disp in disps) { AdditionalParams.Add(new ResultParameter(disp.Group.FirstOrDefault() ?? "", disp.Name, Value)); } Log.Info("Running child steps with {0} = {1} ", names, Value); var runs = RunChildSteps(AdditionalParams, BreakLoopRequested).ToList(); if (BreakLoopRequested.IsCancellationRequested) { break; } runs.ForEach(r => r.WaitForCompletion()); } for (int i = 0; i < selected.Length; i++) { selected[i].SetValue(this, originalValues[i]); } }
/// <summary> /// Tries to deserialize an object from an XElement. /// </summary> /// <param name="element"></param> /// <param name="t"></param> /// <param name="setter"></param> /// <param name="newobj"></param> /// <param name="logWarnings">Whether warning messages should be emitted in case of missing properties.</param> /// <returns>True on success.</returns> public virtual bool TryDeserializeObject(XElement element, ITypeData t, Action <object> setter, object newobj = null, bool logWarnings = true) { if (element.IsEmpty && !element.HasAttributes) { setter(null); return(true); } if (newobj == null) { try { newobj = t.CreateInstance(Array.Empty <object>()); t = TypeData.GetTypeData(newobj); } catch (TargetInvocationException ex) { if (ex.InnerException is System.ComponentModel.LicenseException) { throw new Exception(string.Format("Could not create an instance of '{0}': {1}", t.GetAttribute <DisplayAttribute>().Name, ex.InnerException.Message)); } else { ExceptionDispatchInfo.Capture(ex.InnerException).Throw(); } } } var prevobj = Object; Object = newobj; var t2 = t; if (newobj == null) { throw new ArgumentNullException(nameof(newobj)); } var properties = t2.GetMembers() .Where(x => x.HasAttribute <XmlIgnoreAttribute>() == false) .ToArray(); try { foreach (var prop in properties) { var attr = prop.GetAttribute <XmlAttributeAttribute>(); if (attr == null) { continue; } var name = string.IsNullOrWhiteSpace(attr.AttributeName) ? prop.Name : attr.AttributeName; var attr_value = element.Attribute(XmlConvert.EncodeLocalName(name)); var p = prop as MemberData; if (p != null && attr_value != null && p.Member is PropertyInfo csprop) { try { readContentInternal(csprop.PropertyType, false, () => attr_value.Value, element, out object value); p.SetValue(newobj, value); } catch (Exception e) { if (logWarnings) { Log.Warning(element, "Attribute value '{0}' was not read correctly as a {1}", attr_value.Value, p); Log.Debug(e); } } } } if (properties.FirstOrDefault(x => x.HasAttribute <XmlTextAttribute>()) is IMemberData mem2) { object value; if (mem2.TypeDescriptor is TypeData td && readContentInternal(td.Load(), false, () => element.Value, element, out object _value)) { value = _value; } else { value = StringConvertProvider.FromString(element.Value, mem2.TypeDescriptor, null); } mem2.SetValue(newobj, value); } else { var props = properties.ToLookup(x => x.GetAttributes <XmlElementAttribute>().FirstOrDefault()?.ElementName ?? x.Name); var elements = element.Elements().ToArray(); bool[] visited = new bool[elements.Length]; double order = 0; int foundWithCurrentType = 0; while (true) { double nextOrder = 1000; // since the object might be dynamically adding properties as other props are added. // we need to iterate a bit. Example: Test Plan Reference. int found = visited.Count(x => x); for (int i = 0; i < elements.Length; i++) { var element2 = elements[i]; if (visited[i]) { continue; } if (element2.Attribute(IgnoreMemberXName) is XAttribute attr && attr.Value == "true") { visited[i] = true; continue; } IMemberData property = null; var name = XmlConvert.DecodeName(element2.Name.LocalName); var propertyMatches = props[name]; int hits = 0; foreach (var p in propertyMatches) { if (p.Writable || p.HasAttribute <XmlIgnoreAttribute>()) { property = p; hits++; } } if (0 == hits) { try { if (property == null) { property = t2.GetMember(name); } if (property == null) { property = t2.GetMembers().FirstOrDefault(x => x.Name == name); } } catch { } if (property == null || property.Writable == false) { continue; } hits = 1; } if (hits > 1) { Log.Warning(element2, "Multiple properties named '{0}' are available to the serializer in '{1}' this might give issues in serialization.", element2.Name.LocalName, t.GetAttribute <DisplayAttribute>().Name); } if (property.GetAttribute <DeserializeOrderAttribute>() is DeserializeOrderAttribute orderAttr) { if (order < orderAttr.Order) { if (orderAttr.Order < nextOrder) { nextOrder = orderAttr.Order; } continue; } } else { nextOrder = order; } visited[i] = true; var prev = CurrentMember; CurrentMember = property; try { if (CurrentMember.HasAttribute <XmlIgnoreAttribute>()) // This property shouldn't have been in the file in the first place, but in case it is (because of a change or a bug), we shouldn't try to set it. (E.g. SweepLoopRange.SweepStep) { if (!CurrentMember.HasAttribute <BrowsableAttribute>()) // In the special case we assume that this is some compatibility property that still needs to be set if present in the XML. (E.g. TestPlanReference.DynamicDataContents) { continue; } } if (property is MemberData mem && mem.Member is PropertyInfo Property && Property.PropertyType.HasInterface <IList>() && Property.PropertyType.IsGenericType && Property.HasAttribute <XmlElementAttribute>()) { // Special case to mimic old .NET XmlSerializer behavior var list = (IList)Property.GetValue(newobj); Action <object> setValue = x => list.Add(x); Serializer.Deserialize(element2, setValue, Property.PropertyType.GetGenericArguments().First()); } else { Action <object> setValue = x => { var current = property.GetValue(newobj); property.SetValue(newobj, x); if (false == Equals(current, x)) { // for some value-like type, it may be needed // to set the parent object when a property is changed // example: complex test plan parameters. setter(newobj); } }; Serializer.Deserialize(element2, setValue, property.TypeDescriptor); } }