public void DataObjectFactory_RegisterDataObject_Works() { DataObjectFactory.RegisterDataObject <Utils.PersonDataObject>(); IDataContainer dc = DataContainerBuilder.Create() .Data("person", new Utils.Person { FirstName = "John", LastName = "Doe" }) .Build(); string xml = XmlHelper.SerializeToString(dc); IDataContainer dcNew = XmlHelper.DeserializeFromString <System.Configuration.DataContainer>(xml); Assert.True(dcNew.ContainsData("person")); DataObject dobj = dcNew.Find("person"); Assert.Equal("prsn", dobj.Type); Utils.Person p = dobj.GetValue() as Utils.Person; Assert.Equal("John", p.FirstName); Assert.Equal("Doe", p.LastName); }
/// <summary> /// Create a nested data container. /// </summary> /// <param name="name"></param> /// <param name="containerBuilder"></param> /// <returns></returns> public DataContainerBuilder DataContainer(string name, Action <DataContainerBuilder> containerBuilder) { if (config.ContainsData(name)) { DataContainerEvents.NotifyInformation($"Attempted to add invalid value : {name}"); return(this); } var builder = Create(name); containerBuilder?.Invoke(builder); config.Add(new ContainerDataObject(name, builder.Build())); return(this); }
public void DataContainerAutoUpdater_ShouldAddNewValuesWithMultiLevelData() { string path = Path.GetTempFileName(); DataContainerBase A = (DataContainerBase)DataContainerBuilder.Create("A") .Data("A", 1) .Data("B", 2) .Data("D", 3) .DataContainer("AB", b => b .Data("AB1", 1)) .Build(); A.FilePath = path; A.SaveAsXml(path); var tester = new AutoUpateTester(A); tester.AutoUpdater.PollingInterval = 10; // allow adding tester.AutoUpdater.CanAddItems = true; Assert.False(tester.UpdateStartedInvoked); Assert.False(tester.UpdateFinishedInvoked); IDataContainer Updated = (DataContainerBase)DataContainerBuilder.Create("A") .Data("A", 1) .Data("B", 2) .Data("D", 3) .DataContainer("AB", b => b .Data("AB1", 1) .Data("AB2", 2)) .Build(); Updated.SaveAsXml(path); // wait timer Thread.Sleep((int)tester.AutoUpdater.PollingInterval + 20); Assert.True(tester.UpdateStartedInvoked); Assert.True(tester.UpdateFinishedInvoked); IDataContainer AB = (IDataContainer)A["AB"]; // 1 value added Assert.Equal(2, AB.Count); // check if value exist Assert.True(AB.ContainsData("AB2")); // check it has correct value Assert.Equal(2, (int)AB["AB2"]); File.Delete(path); }
public static void PutValue(this IDataContainer container, string key, object value) { if (container.ContainsData(key)) { container.SetValue(key, value); } else { if (container is IPropertyContainer) { container.Add(DataObjectFactory.GetPropertyObjectFor(key, value)); } else { container.Add(DataObjectFactory.GetDataObjectFor(key, value)); } } }
/// <summary> /// Add new properties from second to first, if they already exist, keep the values. /// Same as <see cref="Union(IDataContainer, IDataContainer)"/> but does operation inplace instead of returning new intance; /// </summary> /// <param name="lhs"></param> /// <param name="rhs"></param> public static bool Merge(this IDataContainer lhs, IDataContainer rhs) { bool result = false; bool innerResult = false; foreach (var data in rhs) { if (lhs.ContainsData(data.Name) == false) { lhs.Add(data); result = true; } else { DataObject lhsData = lhs.Find(data.Name); // No need to update value, but update the details if (data is PropertyObject propRhs && lhsData is PropertyObject propLhs) { result = propLhs.DisplayName != propRhs.DisplayName || propLhs.Category != propRhs.Category || propLhs.Description != propRhs.Description; propLhs.DisplayName = propRhs.DisplayName; propLhs.Category = propRhs.Category; propLhs.Description = propRhs.Description; } if (lhsData.GetValue() is IDataContainer dc) { IDataContainer rhsDC = data.GetValue() as IDataContainer; bool temp = dc.Merge(rhsDC); innerResult = temp || innerResult; } } } return(result || innerResult); }
/// <summary> /// Removes all the properties that are not in second and in first from first /// </summary> /// <param name="lhs"></param> /// <param name="rhs"></param> public static void InplaceIntersect(this IDataContainer lhs, IDataContainer rhs) { var toRemove = new List <DataObject>(); foreach (var data in lhs) { if (rhs.ContainsData(data.Name) == false) { toRemove.Add(data); } else if (data.GetValue() is IDataContainer dc) { var rhsDC = (IDataContainer)rhs[data.Name]; dc.InplaceIntersect(rhsDC); } } foreach (var item in toRemove) { lhs.Remove(item); } }
/// <summary> /// Takes in 2 <see cref="IDataContainer"/> returns a new instance of <see cref="IDataContainer"/> /// which contains all the properties in <paramref name="lhs"/> and <paramref name="rhs"/> /// </summary> /// <param name="lhs"></param> /// <param name="rhs"> LHS V RHS</param> /// <returns></returns> public static IDataContainer Union(this IDataContainer lhs, IDataContainer rhs) { IDataContainer union = lhs is IPropertyContainer ? (IDataContainer) new PropertyContainer() : new DataContainer(); union.Name = lhs.Name; foreach (DataObject obj in lhs) { union.Add(obj); } foreach (DataObject obj in rhs) { if (union.ContainsData(obj.Name) == false) { union.Add(obj); } else { // in case of nested IDataContainer if (obj.GetValue() is IDataContainer dc) { var unionObj = union.Find(obj.Name); IDataContainer unionDC = unionObj.GetValue() as IDataContainer; if (unionDC.IsIdentical(dc) == false) { unionObj.SetValue(unionDC.Union(dc)); } } } } return(union); }