From 1b14b02b3b838ecd5579f4624748f715e9cee5a0 Mon Sep 17 00:00:00 2001 From: "Matthew D. Groves" Date: Sat, 24 Mar 2018 11:22:18 -0400 Subject: [PATCH] Allow .NET objects to be used to construct DataSetDetail Added a constructor that would allow a List of simple .NET objects to be used instead of having to map objects to a Dictionary --- .../DataSetDetailConstructorTests.cs | 83 +++++++++++++++++++ Api.Client/Model/DataSetDetail.cs | 14 +++- 2 files changed, 96 insertions(+), 1 deletion(-) create mode 100644 Api.Client.Tests/ModelsTests/DataSetDetailConstructorTests.cs diff --git a/Api.Client.Tests/ModelsTests/DataSetDetailConstructorTests.cs b/Api.Client.Tests/ModelsTests/DataSetDetailConstructorTests.cs new file mode 100644 index 0000000..33c77f3 --- /dev/null +++ b/Api.Client.Tests/ModelsTests/DataSetDetailConstructorTests.cs @@ -0,0 +1,83 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using Newtonsoft.Json; +using Nexosis.Api.Client.Model; +using Xunit; + +namespace Api.Client.Tests.ModelsTests +{ + public class DataSetDetailConstructorTests + { + #region classes used for testing + internal class TestObject + { + public string Foo { get; set; } + public int Bar { get; set; } + } + + internal class ComplexTestObject + { + public TestObject Complex { get; set; } + public string Abc { get; set; } + } + #endregion + + [Fact] + public void PopulatedByObjects() + { + // arrange + var testObject1 = new TestObject {Foo = Guid.NewGuid().ToString(), Bar = 123 }; + var testObject2 = new TestObject {Foo = Guid.NewGuid().ToString(), Bar = 456 }; + var list = new List {testObject1, testObject2}; + + // act + var dataSetDetail = new DataSetDetail(list); + + // assert + Assert.True(dataSetDetail.Data.Any(d => d.ContainsKey("Foo"))); + Assert.True(dataSetDetail.Data.SingleOrDefault(d => d.ContainsKey("Foo") && d.ContainsValue(testObject1.Foo)) != null); + Assert.True(dataSetDetail.Data.SingleOrDefault(d => d.ContainsKey("Bar") && d.ContainsValue(testObject1.Bar.ToString())) != null); + Assert.True(dataSetDetail.Data.SingleOrDefault(d => d.ContainsKey("Foo") && d.ContainsValue(testObject2.Foo)) != null); + Assert.True(dataSetDetail.Data.SingleOrDefault(d => d.ContainsKey("Bar") && d.ContainsValue(testObject2.Bar.ToString())) != null); + } + + [Fact] + public void CantBePopulatedByComplexObjects() + { + // arrange + var testObject1 = new ComplexTestObject + { + Abc = Guid.NewGuid().ToString(), + Complex = new TestObject {Foo = Guid.NewGuid().ToString(), Bar = 789 } + + }; + var list = new List {testObject1 }; + + // act + void Act() { new DataSetDetail(list); } + + // assert + Assert.Throws((Action) Act); + } + + [Fact] + public void PopulatedByAnonymousObjects() + { + // arrange + var testObject1 = new { Foo = Guid.NewGuid().ToString(), Bar = 777 }; + var testObject2 = new { Foo = Guid.NewGuid().ToString(), Bar = 888 }; + var list = new List { testObject1, testObject2 }; + + // act + var dataSetDetail = new DataSetDetail(list); + + // assert + Assert.True(dataSetDetail.Data.Any(d => d.ContainsKey("Foo"))); + Assert.True(dataSetDetail.Data.SingleOrDefault(d => d.ContainsKey("Foo") && d.ContainsValue(testObject1.Foo)) != null); + Assert.True(dataSetDetail.Data.SingleOrDefault(d => d.ContainsKey("Bar") && d.ContainsValue(testObject1.Bar.ToString())) != null); + Assert.True(dataSetDetail.Data.SingleOrDefault(d => d.ContainsKey("Foo") && d.ContainsValue(testObject2.Foo)) != null); + Assert.True(dataSetDetail.Data.SingleOrDefault(d => d.ContainsKey("Bar") && d.ContainsValue(testObject2.Bar.ToString())) != null); + } + } +} \ No newline at end of file diff --git a/Api.Client/Model/DataSetDetail.cs b/Api.Client/Model/DataSetDetail.cs index cab2719..3afd32b 100644 --- a/Api.Client/Model/DataSetDetail.cs +++ b/Api.Client/Model/DataSetDetail.cs @@ -1,10 +1,23 @@ using System; using System.Collections.Generic; +using Newtonsoft.Json; namespace Nexosis.Api.Client.Model { public class DataSetDetail { + public DataSetDetail() { } + + /// + /// Create a DataSetDetail using a collection of .NET object + /// + /// The objects must be simple objects that can be deserialized into a simple string dictionary + public DataSetDetail(List obj) + { + var json = JsonConvert.SerializeObject(obj); + Data = JsonConvert.DeserializeObject>>(json); + } + /// The data /// The dictionaries added to the list should treat the keys case insensitive. The API ignores case on column names. public List> Data { get; set; } = new List>(); @@ -12,6 +25,5 @@ public class DataSetDetail /// Metadata about each column in the dataset /// This is initialized as a case-insensitive dictionary. The API ignores case for column names. public Dictionary Columns { get; set; } = new Dictionary(StringComparer.OrdinalIgnoreCase); - } } \ No newline at end of file