diff --git a/src/NPoco/ColumnInfo.cs b/src/NPoco/ColumnInfo.cs index c6b4818a..faab6334 100644 --- a/src/NPoco/ColumnInfo.cs +++ b/src/NPoco/ColumnInfo.cs @@ -2,7 +2,6 @@ using System.Collections.Generic; using System.Linq; using System.Reflection; -using System.Text; namespace NPoco { @@ -26,10 +25,11 @@ public class ColumnInfo public string ReferenceMemberName { get; set; } public MemberInfo MemberInfo { get; internal set; } public bool ExactColumnNameMatch { get; set; } + public IReadOnlyDictionary Metadata { get; set; } public static ColumnInfo FromMemberInfo(MemberInfo mi) { - var ci = new ColumnInfo{MemberInfo = mi}; + var ci = new ColumnInfo { MemberInfo = mi }; var attrs = ReflectionUtils.GetCustomAttributes(mi).ToArray(); var colAttrs = attrs.OfType().ToArray(); var columnTypeAttrs = attrs.OfType().ToArray(); diff --git a/src/NPoco/DefaultMapper.cs b/src/NPoco/DefaultMapper.cs index 78a8485c..df7d14c9 100644 --- a/src/NPoco/DefaultMapper.cs +++ b/src/NPoco/DefaultMapper.cs @@ -1,5 +1,5 @@ using System; -using System.Data; +using System.Collections.Generic; using System.Data.Common; using System.Reflection; @@ -7,7 +7,7 @@ namespace NPoco { public abstract class DefaultMapper : IMapper { - public virtual Func GetFromDbConverter(MemberInfo destMemberInfo, Type sourceType) + public virtual Func GetFromDbConverter(MemberInfo destMemberInfo, Type sourceType, IReadOnlyDictionary metadata = null) { var type = destMemberInfo.GetMemberInfoType(); return destMemberInfo != null ? GetFromDbConverter(type, sourceType) : null; @@ -18,7 +18,7 @@ public virtual Func GetFromDbConverter(Type destType, Type sourc return null; } - public virtual Func GetToDbConverter(Type destType, MemberInfo sourceMemberInfo) + public virtual Func GetToDbConverter(Type destType, MemberInfo sourceMemberInfo, IReadOnlyDictionary metadata = null) { return null; } diff --git a/src/NPoco/FluentMappings/ColumnConfigurationBuilder.cs b/src/NPoco/FluentMappings/ColumnConfigurationBuilder.cs index efc5a60e..3c906da7 100644 --- a/src/NPoco/FluentMappings/ColumnConfigurationBuilder.cs +++ b/src/NPoco/FluentMappings/ColumnConfigurationBuilder.cs @@ -1,8 +1,7 @@ using System; using System.Collections.Generic; -using System.Linq.Expressions; using System.Linq; -using System.Reflection; +using System.Linq.Expressions; namespace NPoco.FluentMappings { @@ -118,6 +117,7 @@ public interface IColumnBuilder IColumnBuilder ValueObject(); IColumnBuilder ValueObject(Expression> member); IColumnBuilder ForceToUtc(bool enabled); + IColumnBuilder WithMetadata(string key, object value); } public class ColumnBuilder : IColumnBuilder @@ -156,7 +156,7 @@ public IColumnBuilder WithDbType(Type type) public IColumnBuilder WithDbType() { - return WithDbType(typeof (T)); + return WithDbType(typeof(T)); } public IColumnBuilder Version() @@ -253,5 +253,12 @@ public IColumnBuilder ForceToUtc(bool enabled) _columnDefinition.ForceUtc = enabled; return this; } + + public IColumnBuilder WithMetadata(string key, object value) + { + _columnDefinition.Metadata ??= new Dictionary(1); + _columnDefinition.Metadata.Add(key, value); + return this; + } } } \ No newline at end of file diff --git a/src/NPoco/FluentMappings/ColumnDefinition.cs b/src/NPoco/FluentMappings/ColumnDefinition.cs index 3a9b064e..a2a90ec5 100644 --- a/src/NPoco/FluentMappings/ColumnDefinition.cs +++ b/src/NPoco/FluentMappings/ColumnDefinition.cs @@ -1,4 +1,5 @@ using System; +using System.Collections.Generic; using System.Reflection; namespace NPoco.FluentMappings @@ -26,5 +27,6 @@ public class ColumnDefinition public bool? ValueObjectColumn { get; set; } public string ValueObjectColumnName { get; set; } public bool? ExactColumnNameMatch { get; set; } + public Dictionary Metadata { get; set; } } } \ No newline at end of file diff --git a/src/NPoco/FluentMappings/FluentMappingsPocoDataBuilder.cs b/src/NPoco/FluentMappings/FluentMappingsPocoDataBuilder.cs index cf4b7bc4..f28b6fe3 100644 --- a/src/NPoco/FluentMappings/FluentMappingsPocoDataBuilder.cs +++ b/src/NPoco/FluentMappings/FluentMappingsPocoDataBuilder.cs @@ -9,7 +9,7 @@ public class FluentMappingsPocoDataBuilder : PocoDataBuilder { private readonly Mappings _mappings; - public FluentMappingsPocoDataBuilder(Type type, Mappings mappings, MapperCollection mapper) : + public FluentMappingsPocoDataBuilder(Type type, Mappings mappings, MapperCollection mapper) : base(type, mapper) { _mappings = mappings; @@ -42,7 +42,7 @@ protected override TableInfoPlan GetTableInfo(Type type, ColumnInfo[] columnInfo primaryKey = string.Join(",", originalPk); } } - + a = typeConfig.SequenceName ?? ""; var sequenceName = a.Length == 0 ? null : a; @@ -50,10 +50,10 @@ protected override TableInfoPlan GetTableInfo(Type type, ColumnInfo[] columnInfo // Set autoincrement false if primary key has multiple columns autoIncrement = autoIncrement ? !primaryKey.Contains(',') : autoIncrement; - + // Set auto alias var autoAlias = CreateAlias(type.Name, type); - + return () => new TableInfo { TableName = tableName, @@ -67,10 +67,10 @@ protected override TableInfoPlan GetTableInfo(Type type, ColumnInfo[] columnInfo protected override bool ShouldIncludePrivateColumn(MemberInfo mi, Type type) { - if (_mappings.Config.ContainsKey(type) + if (_mappings.Config.ContainsKey(type) && _mappings.Config[type].ColumnConfiguration.ContainsKey(mi.Name)) return true; - + return base.ShouldIncludePrivateColumn(mi, type); } @@ -80,7 +80,7 @@ protected override ColumnInfo GetColumnInfo(MemberInfo mi, Type type) return base.GetColumnInfo(mi, type); var typeConfig = _mappings.Config[type]; - var columnInfo = new ColumnInfo() {MemberInfo = mi}; + var columnInfo = new ColumnInfo() { MemberInfo = mi }; var key = mi.Name; bool explicitColumns = typeConfig.ExplicitColumns ?? false; @@ -144,8 +144,10 @@ protected override ColumnInfo GetColumnInfo(MemberInfo mi, Type type) } columnInfo.ColumnType = colattr.DbColumnType; + + columnInfo.Metadata = colattr.Metadata; } - + return columnInfo; } } diff --git a/src/NPoco/IMapper.cs b/src/NPoco/IMapper.cs index 1973037c..d6f4d3eb 100644 --- a/src/NPoco/IMapper.cs +++ b/src/NPoco/IMapper.cs @@ -1,5 +1,5 @@ using System; -using System.Data; +using System.Collections.Generic; using System.Data.Common; using System.Reflection; @@ -7,9 +7,9 @@ namespace NPoco { public interface IMapper { - Func GetFromDbConverter(MemberInfo memberInfo, Type sourceType); + Func GetFromDbConverter(MemberInfo memberInfo, Type sourceType, IReadOnlyDictionary metadata = null); Func GetFromDbConverter(Type destType, Type sourceType); Func GetParameterConverter(DbCommand dbCommand, Type sourceType); - Func GetToDbConverter(Type destType, MemberInfo sourceMemberInfo); + Func GetToDbConverter(Type destType, MemberInfo sourceMemberInfo, IReadOnlyDictionary metadata = null); } } \ No newline at end of file diff --git a/src/NPoco/MapperCollection.cs b/src/NPoco/MapperCollection.cs index 511b232e..e2e23fa5 100644 --- a/src/NPoco/MapperCollection.cs +++ b/src/NPoco/MapperCollection.cs @@ -1,7 +1,7 @@ using System; using System.Collections.Generic; -using System.Linq; using System.Data.Common; +using System.Linq; using System.Reflection; namespace NPoco @@ -26,7 +26,7 @@ public void RegisterFactory(Func factory) public ObjectFactoryDelegate GetFactory(Type type) { - return Factories.ContainsKey(type) ? Factories[type] : null; + return Factories.TryGetValue(type, out var factory) ? factory : null; } public bool HasFactory(Type type) @@ -66,16 +66,16 @@ internal Func FindFromDbConverter(Type destType, Type srcType) return FromDbConverterCache.Get(key, () => Find(x => x.GetFromDbConverter(destType, srcType))); } - internal Func FindFromDbConverter(MemberInfo destInfo, Type srcType) + internal Func FindFromDbConverter(MemberInfo destInfo, Type srcType, IReadOnlyDictionary metadata = null) { var key = new { DestInfo = destInfo, SrcType = srcType }; - return FromDbConverterCache.Get(key, () => Find(x => x.GetFromDbConverter(destInfo, srcType))); + return FromDbConverterCache.Get(key, () => Find(x => x.GetFromDbConverter(destInfo, srcType, metadata))); } - internal Func FindToDbConverter(Type destType, MemberInfo srcInfo) + internal Func FindToDbConverter(Type destType, MemberInfo srcInfo, IReadOnlyDictionary metadata = null) { var key = new { DestType = destType, SrcInfo = srcInfo }; - return ToDbConverterCache.Get(key, () => Find(x => x.GetToDbConverter(destType, srcInfo))); + return ToDbConverterCache.Get(key, () => Find(x => x.GetToDbConverter(destType, srcInfo, metadata))); } } } \ No newline at end of file diff --git a/src/NPoco/MappingHelper.cs b/src/NPoco/MappingHelper.cs index 3fa2a0d6..7e8396ff 100644 --- a/src/NPoco/MappingHelper.cs +++ b/src/NPoco/MappingHelper.cs @@ -1,6 +1,4 @@ using System; -using System.Collections.Generic; -using System.Data; using System.Linq; using System.Reflection; @@ -18,21 +16,24 @@ public static Func GetConverter(MapperCollection mapper, PocoCol // Get converter from the mapper if (mapper != null) { - converter = pc != null && pc.MemberInfoData != null ? mapper.FindFromDbConverter(pc.MemberInfoData.MemberInfo, srcType) : mapper.FindFromDbConverter(dstType, srcType); + converter = pc != null && pc.MemberInfoData != null + ? mapper.FindFromDbConverter(pc.MemberInfoData.MemberInfo, srcType, pc.Metadata) + : mapper.FindFromDbConverter(dstType, srcType); + if (converter != null) return converter; } if (pc != null && pc.SerializedColumn && mapper?.ColumnSerializer != null) { - converter = src => mapper.ColumnSerializer.Deserialize((string) src, dstType); + converter = src => mapper.ColumnSerializer.Deserialize((string)src, dstType); return converter; } // Standard DateTime->Utc mapper if (pc != null && pc.ForceToUtc && srcType == typeof(DateTime) && (dstType == typeof(DateTime) || dstType == typeof(DateTime?))) { - converter = src => new DateTime(((DateTime) src).Ticks, DateTimeKind.Utc); + converter = src => new DateTime(((DateTime)src).Ticks, DateTimeKind.Utc); return converter; } @@ -54,7 +55,7 @@ public static Func GetConverter(MapperCollection mapper, PocoCol } else if (srcType == typeof(string) && (dstType == typeof(Guid) || dstType == typeof(Guid?))) { - converter = src => Guid.Parse((string) src); + converter = src => Guid.Parse((string)src); } else if ((!pc?.ValueObjectColumn ?? true) && !dstType.IsAssignableFrom(srcType)) { diff --git a/src/NPoco/PocoColumn.cs b/src/NPoco/PocoColumn.cs index 92985585..7c8ea6c2 100644 --- a/src/NPoco/PocoColumn.cs +++ b/src/NPoco/PocoColumn.cs @@ -54,6 +54,7 @@ public Type ColumnType public bool ValueObjectColumn { get; set; } public string ValueObjectColumnName { get; set; } public bool ExactColumnNameMatch { get; set; } + public IReadOnlyDictionary Metadata { get; set; } internal void SetMemberAccessors(List memberAccessors) { @@ -82,8 +83,8 @@ public virtual void SetValue(object target, object val) public virtual object GetValue(object target) { - return valueObjectGetter != null - ? valueObjectGetter(GetRecursiveValue(target) ?? fastCreate.Create(null)) + return valueObjectGetter != null + ? valueObjectGetter(GetRecursiveValue(target) ?? fastCreate.Create(null)) : GetRecursiveValue(target); } diff --git a/src/NPoco/PocoDataBuilder.cs b/src/NPoco/PocoDataBuilder.cs index f59e8f7e..c1899650 100644 --- a/src/NPoco/PocoDataBuilder.cs +++ b/src/NPoco/PocoDataBuilder.cs @@ -1,10 +1,7 @@ using System; -using System.Collections; using System.Collections.Generic; using System.Linq; using System.Reflection; -using NPoco.FluentMappings; -using NPoco.RowMappers; namespace NPoco { @@ -65,7 +62,7 @@ public ColumnInfo[] GetColumnInfos(Type type) public static bool IsDictionaryType(Type type) { - return new[] {typeof(object), typeof(IDictionary), typeof(Dictionary)}.Contains(type) + return new[] { typeof(object), typeof(IDictionary), typeof(Dictionary) }.Contains(type) || (type.GetTypeInfo().IsGenericType && type.GetGenericTypeDefinition() == typeof(Dictionary<,>) && type.GetGenericArguments().First() == typeof(string)); } @@ -111,14 +108,14 @@ private static IEnumerable GetPocoColumns(IEnumerable me yield return member.PocoColumn; break; case ReferenceType.None: - { - yield return member.PocoColumn; - foreach (var pocoMemberChild in GetPocoColumns(member.PocoMemberChildren)) { - yield return pocoMemberChild; + yield return member.PocoColumn; + foreach (var pocoMemberChild in GetPocoColumns(member.PocoMemberChildren)) + { + yield return pocoMemberChild; + } + break; } - break; - } } } } @@ -136,8 +133,8 @@ public IEnumerable GetPocoMembers(ColumnInfo[] columnInfos, List if (columnInfo.ReferenceType == ReferenceType.Many) { var genericArguments = memberInfoType.GetGenericArguments(); - memberInfoType = genericArguments.Any() - ? genericArguments.First() + memberInfoType = genericArguments.Any() + ? genericArguments.First() : memberInfoType.GetTypeWithGenericTypeDefinitionOf(typeof(IList<>)).GetGenericArguments().First(); } @@ -175,7 +172,7 @@ public IEnumerable GetPocoMembers(ColumnInfo[] columnInfos, List var fastCreate = GetFastCreate(memberType, Mapper, isList, isDynamic); var columnName = GetColumnName(capturedPrefix, capturedColumnInfo.ColumnName ?? capturedMemberInfo.Name); var memberInfoData = new MemberInfoData(capturedMemberInfo); - + yield return tableInfo => { var pc = new PocoColumn @@ -196,6 +193,7 @@ public IEnumerable GetPocoMembers(ColumnInfo[] columnInfos, List VersionColumnType = capturedColumnInfo.VersionColumnType, SerializedColumn = capturedColumnInfo.SerializedColumn, ValueObjectColumn = capturedColumnInfo.ValueObjectColumn, + Metadata = capturedColumnInfo.Metadata }; if (pc.ValueObjectColumn) diff --git a/test/NPoco.Tests/Common/FirebirdDefaultMapper.cs b/test/NPoco.Tests/Common/FirebirdDefaultMapper.cs index a851f4b0..f761272f 100644 --- a/test/NPoco.Tests/Common/FirebirdDefaultMapper.cs +++ b/test/NPoco.Tests/Common/FirebirdDefaultMapper.cs @@ -1,20 +1,20 @@ using System; +using System.Collections.Generic; using System.Reflection; -using NPoco; namespace NPoco.Tests.Common { - internal class FirebirdDefaultMapper: DefaultMapper + internal class FirebirdDefaultMapper : DefaultMapper { private bool isNullable(Type type) { - return (type.GetTypeInfo().IsGenericType && type.GetGenericTypeDefinition() == typeof (Nullable<>)); + return (type.GetTypeInfo().IsGenericType && type.GetGenericTypeDefinition() == typeof(Nullable<>)); } public override Func GetFromDbConverter(Type DestType, Type SourceType) { // Db:String -> Guid - if ((DestType == typeof (Guid)) && (SourceType == typeof (string))) + if ((DestType == typeof(Guid)) && (SourceType == typeof(string))) { return src => Guid.Parse((string)src); } @@ -23,9 +23,9 @@ public override Func GetFromDbConverter(Type DestType, Type Sour if (isNullable(DestType)) { var underlyingType = Nullable.GetUnderlyingType(DestType); - if (underlyingType == typeof (Guid) ) + if (underlyingType == typeof(Guid)) { - return src => (src == null ? (Guid?) null : Guid.Parse((string) src)); + return src => (src == null ? (Guid?)null : Guid.Parse((string)src)); } } @@ -50,7 +50,7 @@ public override Func GetFromDbConverter(Type DestType, Type Sour return base.GetFromDbConverter(DestType, SourceType); } - public override Func GetToDbConverter(Type destType, MemberInfo sourceMemberInfo) + public override Func GetToDbConverter(Type destType, MemberInfo sourceMemberInfo, IReadOnlyDictionary metadata = null) { if ((sourceMemberInfo.GetMemberInfoType() == typeof(StringObject)) && (destType == typeof(string))) { diff --git a/test/NPoco.Tests/Common/User.cs b/test/NPoco.Tests/Common/User.cs index c1d2b2c7..04fde5c8 100644 --- a/test/NPoco.Tests/Common/User.cs +++ b/test/NPoco.Tests/Common/User.cs @@ -1,5 +1,4 @@ using System; -using NPoco; namespace NPoco.Tests.Common { @@ -43,7 +42,7 @@ public User() public class StringObject { public string MyValue { get; set; } - + public override string ToString() { return MyValue; diff --git a/test/NPoco.Tests/DecoratedTests/CRUDTests/UpdateTests.cs b/test/NPoco.Tests/DecoratedTests/CRUDTests/UpdateTests.cs index 1ddae3fa..e0add32e 100644 --- a/test/NPoco.Tests/DecoratedTests/CRUDTests/UpdateTests.cs +++ b/test/NPoco.Tests/DecoratedTests/CRUDTests/UpdateTests.cs @@ -1,11 +1,11 @@ -using System; +using Newtonsoft.Json; +using NPoco.Tests.Common; +using NUnit.Framework; +using System; using System.Collections.Generic; using System.Data; using System.Linq; using System.Reflection; -using Newtonsoft.Json; -using NPoco.Tests.Common; -using NUnit.Framework; namespace NPoco.Tests.DecoratedTests.CRUDTests { @@ -19,7 +19,7 @@ public void UpdatePrimaryKeyObject() Assert.IsNotNull(poco); poco.Age = InMemoryUsers[1].Age + 100; - poco.Savings = (Decimal) 1234.23; + poco.Savings = (Decimal)1234.23; Database.Update(poco); var verify = Database.SingleOrDefaultById(InMemoryUsers[1].UserId); @@ -38,7 +38,7 @@ public void UpdatePrimaryKeyObjectOverridingPrimaryKey() Assert.IsNotNull(poco); poco.Age = InMemoryUsers[1].Age + 100; - poco.Savings = (Decimal) 1234.23; + poco.Savings = (Decimal)1234.23; Database.Update(poco, InMemoryUsers[2].UserId); var verify = Database.SingleOrDefaultById(InMemoryUsers[2].UserId); @@ -84,7 +84,7 @@ public void UpdateWithFields() Assert.IsNotNull(poco); poco.Age = poco.Age + 100; - poco.Savings = (Decimal) 1234.23; + poco.Savings = (Decimal)1234.23; Database.Update(poco, x => x.Age); var verify = Database.SingleOrDefaultById(1); @@ -232,7 +232,7 @@ public class UserModel public class MyMapper : DefaultMapper { - public override Func GetToDbConverter(Type destType, MemberInfo sourceMemberInfo) + public override Func GetToDbConverter(Type destType, MemberInfo sourceMemberInfo, IReadOnlyDictionary metadata = null) { if ((destType == typeof(string)) && (sourceMemberInfo.GetMemberInfoType() == typeof(IDictionary))) { diff --git a/test/NPoco.Tests/FluentMappings/MapTests.cs b/test/NPoco.Tests/FluentMappings/MapTests.cs index 8d4a02d0..2047f483 100644 --- a/test/NPoco.Tests/FluentMappings/MapTests.cs +++ b/test/NPoco.Tests/FluentMappings/MapTests.cs @@ -1,6 +1,7 @@ using NPoco.FluentMappings; using NPoco.Tests.Common; using NUnit.Framework; +using System.Linq; namespace NPoco.Tests.FluentMappings { @@ -83,10 +84,10 @@ public void InheritColumns() { var typeDefinition = new TypeDefinition(typeof(User)); var map = new TestMap(typeDefinition); - + var typeDefinition1 = new TypeDefinition(typeof(Supervisor)); var map1 = new SupervisorMap(typeDefinition1); - + Assert.AreEqual(4, typeDefinition1.ColumnConfiguration.Count); Assert.IsTrue(typeDefinition1.ColumnConfiguration["Age"].IgnoreColumn ?? false); Assert.IsTrue(typeDefinition1.ColumnConfiguration["IsSupervisor"].ResultColumn ?? false); @@ -103,6 +104,15 @@ public void InheritColumnsButRemoveColumnsNotFound() Assert.AreEqual(1, typeDefinition1.ColumnConfiguration.Count); } + + [Test] + public void MetadataDefinition() + { + var typeDefinition = new TypeDefinition(typeof(User)); + var map = new TestMetadataMap(typeDefinition); + + Assert.AreEqual("TestKey", typeDefinition.ColumnConfiguration["Name"].Metadata.Keys.First()); + } } public class TestMap : Map @@ -113,4 +123,12 @@ public TestMap(TypeDefinition typeDefinition) : base(typeDefinition) Columns(x => x.Column(y => y.Days).Result()); } } + + public class TestMetadataMap : Map + { + public TestMetadataMap(TypeDefinition typeDefinition) : base(typeDefinition) + { + Columns(x => x.Column(y => y.Name).WithMetadata("TestKey", new object())); + } + } } diff --git a/test/NPoco.Tests/NewMapper/NewMapperTests.cs b/test/NPoco.Tests/NewMapper/NewMapperTests.cs index 666beb22..84d58806 100644 --- a/test/NPoco.Tests/NewMapper/NewMapperTests.cs +++ b/test/NPoco.Tests/NewMapper/NewMapperTests.cs @@ -1,13 +1,13 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Reflection; -using NPoco.Expressions; +using NPoco.Expressions; using NPoco.fastJSON; using NPoco.Linq; using NPoco.Tests.Common; using NPoco.Tests.NewMapper.Models; using NUnit.Framework; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Reflection; namespace NPoco.Tests.NewMapper { @@ -654,7 +654,7 @@ public void Test28A() public class TestMapper : DefaultMapper { - public override Func GetFromDbConverter(MemberInfo destType, Type sourceType) + public override Func GetFromDbConverter(MemberInfo destType, Type sourceType, IReadOnlyDictionary metadata = null) { if (destType.GetMemberInfoType() == typeof(Test28AClass.Nest4) && sourceType == typeof(string)) { @@ -726,7 +726,7 @@ public void Test32() public void Test33() { var users = Database.Query() - .WhereSql(x=> new Sql($"{x.DatabaseType.EscapeTableName(x.PocoData.TableInfo.AutoAlias)}.UserId in (@list)", new {list = new[] {2}})) + .WhereSql(x => new Sql($"{x.DatabaseType.EscapeTableName(x.PocoData.TableInfo.AutoAlias)}.UserId in (@list)", new { list = new[] { 2 } })) .Where(x => x.UserId.In(new[] { 1, 2 })) .OrderBy(x => x.UserId) .ToList(); @@ -751,8 +751,8 @@ public void Test34() [Test] public void Test35() { - var data = new Result35.ResultData() {Name = "Bob", Age = 66}; - var result = Database.Single("select @0 as Data", JSON.ToJSON(new[] {data})); + var data = new Result35.ResultData() { Name = "Bob", Age = 66 }; + var result = Database.Single("select @0 as Data", JSON.ToJSON(new[] { data })); Assert.AreEqual(data.Name, result.Data[0].Name); Assert.AreEqual(data.Age, result.Data[0].Age); }