object fetchObject(Type t, Func <object, int, bool> test, string src) { IList objects = null; if (src != null) { var containerType = PluginManager.LocateType(src); if (containerType != null) { objects = (IList)ComponentSettings.GetCurrent(containerType); } } if (objects == null) { objects = ComponentSettingsList.GetContainer(t); } var exact = objects.Cast <object>().Where(test).Where(o => o.GetType().DescendsTo(t)).FirstOrDefault(); if (exact != null) { return(exact); } return(objects.Cast <object>().FirstOrDefault(x => x.GetType().DescendsTo(t))); }
/// <summary> Serialization implementation. </summary> public override bool Serialize(XElement elem, object obj, ITypeData expectedType) { if (obj == null) { return(false); } Type type = obj.GetType(); if (obj is IResource && ComponentSettingsList.HasContainer(type)) { // source was set by something else. Assume it can deserialize as well. if (false == string.IsNullOrEmpty(elem.Attribute("Source")?.Value as string)) { return(false); } // If the next thing on the stack is a CollectionSerializer, it means that we are deserializing a ComponentSettingsList. // but if it is a ObjectSerializer it is probably a nested(stacked) resource property. var prevSerializer = Serializer.SerializerStack.FirstOrDefault(x => x is CollectionSerializer || x is ObjectSerializer); var collectionSerializer = prevSerializer as CollectionSerializer; if (collectionSerializer != null && collectionSerializer.ComponentSettingsSerializing.Contains(obj)) { if (checkRentry.Contains(obj)) { return(false); } checkRentry.Add(obj); try { var result = Serializer.Serialize(elem, obj, expectedType); if (result) { elem.SetAttributeValue("Source", ""); // set src to "" to show that it should not be deserialized by reference. } return(result); } finally { checkRentry.Remove(obj); } } var container = ComponentSettingsList.GetContainer(type); var index = container.IndexOf(obj); if (index != -1) { elem.Value = (obj as IResource).Name ?? index.ToString(); elem.SetAttributeValue("Source", container.GetType().FullName); } // important to return true, otherwise it will serialize as a new value. return(true); } return(false); }
/// <summary> Serialization implementation. </summary> public override bool Serialize(XElement elem, object obj, ITypeData expectedType) { if (obj is IConstResourceProperty == false) { return(false); } if (checkRentry.Contains(obj)) { return(false); } checkRentry.Add(obj); try { IConstResourceProperty port = (IConstResourceProperty)obj; elem.SetAttributeValue("Name", port.Name); IList settings = ComponentSettingsList.GetContainer(port.Device.GetType()); if (port.Device != null && settings != null) { XElement device = new XElement("Device"); device.SetAttributeValue("type", settings.GetType().Name); if (Serializer.Serialize(device, port.Device, TypeData.FromType(port.GetType()))) { elem.Add(device); } } else { elem.Add(new XElement("Device")); } return(true); } finally { checkRentry.Remove(obj); } }
/// <summary> Deserialization implementation. </summary> public override bool Deserialize(XElement elem, ITypeData _t, Action <object> setter) { var t = _t.AsTypeData()?.Type; if (t != null && t.DescendsTo(typeof(IResource)) && ComponentSettingsList.HasContainer(t)) { var srcattr = elem.Attribute("Source"); string src = null; if (srcattr != null) { src = srcattr.Value; } if (elem.HasElements || src == "") { return(false); } else { var content = elem.Value.Trim(); Serializer.DeferLoad(() => { // we need to load this asynchronously to avoid recursively // serializing another ComponentSettings. if (string.IsNullOrWhiteSpace(content)) { setter(null); return; } var obj = fetchObject(t, (o, i) => (o as IResource).Name.Trim() == content, src); if (obj != null) { if (obj is IResource resource && resource.Name != content && !string.IsNullOrWhiteSpace(content)) { TestPlanChanged = true; var msg = $"Missing '{content}'. Using '{resource.Name}' instead."; if (elem.Parent.Element("Name") != null) { msg = $"Missing '{content}' used by '{elem.Parent.Element("Name").Value}.{elem.Name.ToString()}. Using '{resource.Name}' instead.'"; } Serializer.PushError(elem, msg); } setter(obj); } else { TestPlanChanged = true; var msg = $"Missing '{content}'."; if (elem.Parent.Element("Name") != null) { msg = $"Missing '{content}' used by '{elem.Parent.Element("Name").Value}.{elem.Name.ToString()}'"; } Serializer.PushError(elem, msg); } }); return(true); } } return(false); }