Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
39 changes: 39 additions & 0 deletions Compare-NET-Objects-Tests/CompareClassTests.cs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
using System;
using System.Collections.Generic;
using System.Linq;
using KellermanSoftware.CompareNetObjects;
using KellermanSoftware.CompareNetObjectsTests.TestClasses;
using NUnit.Framework;
Expand Down Expand Up @@ -216,6 +217,44 @@ public void PrivateFieldInBaseClassNegative()
}
#endregion

#region Backing Field Tests
[Test]
public void BackingFieldPositive()
{
RecipeDetail detail1 = new RecipeDetail(true, "Toffee");
detail1.Ingredient = "Crunchy Chocolate";

RecipeDetail detail2 = new RecipeDetail(true, "Crunchy Frogs");
detail2.Ingredient = "Crunchy Chocolate";

_compare.Config.ComparePrivateFields = true;
_compare.Config.CompareBackingFields = false;
var result = _compare.Compare(detail1, detail2);
Assert.IsTrue(result.AreEqual);
Assert.IsTrue(result.Differences.Count == 0);
_compare.Config.ComparePrivateFields = false;
_compare.Config.CompareBackingFields = true;
}

[Test]
public void BackingFieldNegative()
{
RecipeDetail detail1 = new RecipeDetail(true, "Toffee");
detail1.Ingredient = "Crunchy Chocolate";

RecipeDetail detail2 = new RecipeDetail(true, "Crunchy Frogs");
detail2.Ingredient = "Crunchy Chocolate";

_compare.Config.ComparePrivateFields = true;
_compare.Config.CompareBackingFields = true;
var result = _compare.Compare(detail1, detail2);
Assert.IsFalse(result.AreEqual);
Assert.IsTrue(result.Differences.Any(dif => dif.PropertyName == "<SecretIngredient>k__BackingField"));
_compare.Config.ComparePrivateFields = false;
_compare.Config.CompareBackingFields = true;
}
#endregion

#endif

#region InterfaceMembers
Expand Down
59 changes: 35 additions & 24 deletions Compare-NET-Objects/Cache.cs
Original file line number Diff line number Diff line change
Expand Up @@ -68,35 +68,46 @@ public static IEnumerable<FieldInfo> GetFieldInfo(ComparisonConfig config, Type
FieldInfo[] currentFields;

#if !NETSTANDARD1_3
//All the implementation examples that I have seen for dynamic objects use private fields or properties
if (( config.ComparePrivateFields || isDynamicType) && !config.CompareStaticFields)
BindingFlags flags = BindingFlags.Public | BindingFlags.Instance;
if (config.ComparePrivateFields || isDynamicType)
{
List<FieldInfo> list = new List<FieldInfo>();
Type t = type;
do
{
list.AddRange(t.GetFields(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance));
t = t.BaseType;
} while (t != null);
currentFields = list.ToArray();
flags |= BindingFlags.NonPublic;
}
else if ((config.ComparePrivateFields || isDynamicType) && config.CompareStaticFields)
if (config.CompareStaticFields)
{
List<FieldInfo> list = new List<FieldInfo>();
Type t = type;
do
{
list.AddRange(
t.GetFields(BindingFlags.Public | BindingFlags.Instance | BindingFlags.NonPublic |
BindingFlags.Static));
t = t.BaseType;
} while (t != null);
currentFields = list.ToArray();
flags |= BindingFlags.Static;
}
else
#endif
currentFields = type.GetFields(); //Default is public instance and static

Func<FieldInfo, bool> fieldIsBacking = field => field.Name.Contains("k__BackingField");
List<FieldInfo> list = new List<FieldInfo>();
Type t = type;
do
{
foreach (var field in t.GetFields(flags))
{
if (!config.ComparePrivateFields)
{
list.Add(field);
}
else if (config.ComparePrivateFields && !config.CompareBackingFields && !fieldIsBacking(field))
{
list.Add(field);
}
else if (config.ComparePrivateFields && config.CompareBackingFields)
{
list.Add(field);
}
else if (isDynamicType)
{
list.Add(field);
}
}
t = t.BaseType;
} while (t != null);
currentFields = list.ToArray();
#else
currentFields = type.GetFields(); //Default is public instance and static
#endif
if (config.Caching)
_fieldCache.Add(type, currentFields);

Expand Down
11 changes: 11 additions & 0 deletions Compare-NET-Objects/ComparisonConfig.cs
Original file line number Diff line number Diff line change
Expand Up @@ -316,6 +316,16 @@ public void CustomPropertyComparer<TClass>(Expression<Func<TClass, object>> cust
public bool ComparePrivateFields { get; set; }
#endif

#if !NETSTANDARD1_3
/// <summary>
/// If true and <see cref="ComparePrivateFields"/> true, then backing fields will be compared. The default is true. Silverlight and WinRT restricts access to private variables.
/// </summary>
#if !NETSTANDARD
[DataMember]
#endif
public bool CompareBackingFields { get; set; }
#endif

/// <summary>
/// If true, static properties will be compared. The default is true.
/// </summary>
Expand Down Expand Up @@ -643,6 +653,7 @@ public void Reset()
#if !NETSTANDARD1_3
ComparePrivateProperties = false;
ComparePrivateFields = false;
CompareBackingFields = true;
#endif
CustomPropertyComparers = new Dictionary<string, BaseTypeComparer>();
CompareChildren = true;
Expand Down