864 lines
27 KiB
C#
864 lines
27 KiB
C#
// Copyright (c) .NET Foundation. All rights reserved.
|
|
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
|
|
|
using System;
|
|
using System.Collections.Generic;
|
|
using System.Linq;
|
|
using System.Reflection;
|
|
using Xunit;
|
|
|
|
namespace Microsoft.Extensions.Internal
|
|
{
|
|
public class PropertyHelperTest
|
|
{
|
|
[Fact]
|
|
public void PropertyHelper_ReturnsNameCorrectly()
|
|
{
|
|
// Arrange
|
|
var anonymous = new { foo = "bar" };
|
|
var property = PropertyHelper.GetProperties(anonymous.GetType()).First().Property;
|
|
|
|
// Act
|
|
var helper = new PropertyHelper(property);
|
|
|
|
// Assert
|
|
Assert.Equal("foo", property.Name);
|
|
Assert.Equal("foo", helper.Name);
|
|
}
|
|
|
|
[Fact]
|
|
public void PropertyHelper_ReturnsValueCorrectly()
|
|
{
|
|
// Arrange
|
|
var anonymous = new { bar = "baz" };
|
|
var property = PropertyHelper.GetProperties(anonymous.GetType()).First().Property;
|
|
|
|
// Act
|
|
var helper = new PropertyHelper(property);
|
|
|
|
// Assert
|
|
Assert.Equal("bar", helper.Name);
|
|
Assert.Equal("baz", helper.GetValue(anonymous));
|
|
}
|
|
|
|
[Fact]
|
|
public void PropertyHelper_ReturnsGetterDelegate()
|
|
{
|
|
// Arrange
|
|
var anonymous = new { bar = "baz" };
|
|
var property = PropertyHelper.GetProperties(anonymous.GetType()).First().Property;
|
|
|
|
// Act
|
|
var helper = new PropertyHelper(property);
|
|
|
|
// Assert
|
|
Assert.NotNull(helper.ValueGetter);
|
|
Assert.Equal("baz", helper.ValueGetter(anonymous));
|
|
}
|
|
|
|
[Fact]
|
|
public void SetValue_SetsPropertyValue()
|
|
{
|
|
// Arrange
|
|
var expected = "new value";
|
|
var instance = new BaseClass { PropA = "old value" };
|
|
var helper = PropertyHelper.GetProperties(
|
|
instance.GetType()).First(prop => prop.Name == "PropA");
|
|
|
|
// Act
|
|
helper.SetValue(instance, expected);
|
|
|
|
// Assert
|
|
Assert.Equal(expected, instance.PropA);
|
|
}
|
|
|
|
[Fact]
|
|
public void PropertyHelper_ReturnsSetterDelegate()
|
|
{
|
|
// Arrange
|
|
var expected = "new value";
|
|
var instance = new BaseClass { PropA = "old value" };
|
|
var helper = PropertyHelper.GetProperties(
|
|
instance.GetType()).First(prop => prop.Name == "PropA");
|
|
|
|
// Act and Assert
|
|
Assert.NotNull(helper.ValueSetter);
|
|
helper.ValueSetter(instance, expected);
|
|
|
|
// Assert
|
|
Assert.Equal(expected, instance.PropA);
|
|
}
|
|
|
|
[Fact]
|
|
public void PropertyHelper_ReturnsValueCorrectly_ForValueTypes()
|
|
{
|
|
// Arrange
|
|
var anonymous = new { foo = 32 };
|
|
var property = PropertyHelper.GetProperties(anonymous.GetType()).First().Property;
|
|
|
|
// Act
|
|
var helper = new PropertyHelper(property);
|
|
|
|
// Assert
|
|
Assert.Equal("foo", helper.Name);
|
|
Assert.Equal(32, helper.GetValue(anonymous));
|
|
}
|
|
|
|
[Fact]
|
|
public void PropertyHelper_ReturnsCachedPropertyHelper()
|
|
{
|
|
// Arrange
|
|
var anonymous = new { foo = "bar" };
|
|
|
|
// Act
|
|
var helpers1 = PropertyHelper.GetProperties(anonymous.GetType().GetTypeInfo());
|
|
var helpers2 = PropertyHelper.GetProperties(anonymous.GetType().GetTypeInfo());
|
|
|
|
// Assert
|
|
Assert.Single(helpers1);
|
|
Assert.Same(helpers1, helpers2);
|
|
Assert.Same(helpers1[0], helpers2[0]);
|
|
}
|
|
|
|
[Fact]
|
|
public void PropertyHelper_DoesNotChangeUnderscores()
|
|
{
|
|
// Arrange
|
|
var anonymous = new { bar_baz2 = "foo" };
|
|
|
|
// Act + Assert
|
|
var helper = Assert.Single(PropertyHelper.GetProperties(anonymous.GetType().GetTypeInfo()));
|
|
Assert.Equal("bar_baz2", helper.Name);
|
|
}
|
|
|
|
[Fact]
|
|
public void PropertyHelper_DoesNotFindPrivateProperties()
|
|
{
|
|
// Arrange
|
|
var anonymous = new PrivateProperties();
|
|
|
|
// Act + Assert
|
|
var helper = Assert.Single(PropertyHelper.GetProperties(anonymous.GetType().GetTypeInfo()));
|
|
Assert.Equal("Prop1", helper.Name);
|
|
}
|
|
|
|
[Fact]
|
|
public void PropertyHelper_DoesNotFindStaticProperties()
|
|
{
|
|
// Arrange
|
|
var anonymous = new Static();
|
|
|
|
// Act + Assert
|
|
var helper = Assert.Single(PropertyHelper.GetProperties(anonymous.GetType().GetTypeInfo()));
|
|
Assert.Equal("Prop5", helper.Name);
|
|
}
|
|
|
|
#if NETSTANDARD || NETCOREAPP
|
|
[Fact]
|
|
public void PropertyHelper_RefStructProperties()
|
|
{
|
|
// Arrange
|
|
var obj = new RefStructProperties();
|
|
|
|
// Act + Assert
|
|
var helper = Assert.Single(PropertyHelper.GetProperties(obj.GetType().GetTypeInfo()));
|
|
Assert.Equal("Prop5", helper.Name);
|
|
}
|
|
#elif NET46 || NET461
|
|
#else
|
|
#error Unknown TFM - update the set of TFMs where we test for ref structs
|
|
#endif
|
|
|
|
[Fact]
|
|
public void PropertyHelper_DoesNotFindSetOnlyProperties()
|
|
{
|
|
// Arrange
|
|
var anonymous = new SetOnly();
|
|
|
|
// Act + Assert
|
|
var helper = Assert.Single(PropertyHelper.GetProperties(anonymous.GetType().GetTypeInfo()));
|
|
Assert.Equal("Prop6", helper.Name);
|
|
}
|
|
|
|
[Theory]
|
|
[InlineData(typeof(int?))]
|
|
[InlineData(typeof(DayOfWeek?))]
|
|
public void PropertyHelper_WorksForNullablePrimitiveAndEnumTypes(Type nullableType)
|
|
{
|
|
// Act
|
|
var properties = PropertyHelper.GetProperties(nullableType);
|
|
|
|
// Assert
|
|
Assert.Empty(properties);
|
|
}
|
|
|
|
[Fact]
|
|
public void PropertyHelper_UnwrapsNullableTypes()
|
|
{
|
|
// Arrange
|
|
var myType = typeof(MyStruct?);
|
|
|
|
// Act
|
|
var properties = PropertyHelper.GetProperties(myType);
|
|
|
|
// Assert
|
|
var property = Assert.Single(properties);
|
|
Assert.Equal("Foo", property.Name);
|
|
}
|
|
|
|
[Fact]
|
|
public void PropertyHelper_WorksForStruct()
|
|
{
|
|
// Arrange
|
|
var anonymous = new MyProperties();
|
|
|
|
anonymous.IntProp = 3;
|
|
anonymous.StringProp = "Five";
|
|
|
|
// Act + Assert
|
|
var helper1 = Assert.Single(PropertyHelper.GetProperties(anonymous.GetType().GetTypeInfo()).Where(prop => prop.Name == "IntProp"));
|
|
var helper2 = Assert.Single(PropertyHelper.GetProperties(anonymous.GetType().GetTypeInfo()).Where(prop => prop.Name == "StringProp"));
|
|
Assert.Equal(3, helper1.GetValue(anonymous));
|
|
Assert.Equal("Five", helper2.GetValue(anonymous));
|
|
}
|
|
|
|
[Fact]
|
|
public void PropertyHelper_ForDerivedClass()
|
|
{
|
|
// Arrange
|
|
var derived = new DerivedClass { PropA = "propAValue", PropB = "propBValue" };
|
|
|
|
// Act
|
|
var helpers = PropertyHelper.GetProperties(derived.GetType().GetTypeInfo()).ToArray();
|
|
|
|
// Assert
|
|
Assert.NotNull(helpers);
|
|
Assert.Equal(2, helpers.Length);
|
|
|
|
var propAHelper = Assert.Single(helpers.Where(h => h.Name == "PropA"));
|
|
var propBHelper = Assert.Single(helpers.Where(h => h.Name == "PropB"));
|
|
|
|
Assert.Equal("propAValue", propAHelper.GetValue(derived));
|
|
Assert.Equal("propBValue", propBHelper.GetValue(derived));
|
|
}
|
|
|
|
[Fact]
|
|
public void PropertyHelper_ForDerivedClass_WithNew()
|
|
{
|
|
// Arrange
|
|
var derived = new DerivedClassWithNew { PropA = "propAValue" };
|
|
|
|
// Act
|
|
var helpers = PropertyHelper.GetProperties(derived.GetType().GetTypeInfo()).ToArray();
|
|
|
|
// Assert
|
|
Assert.NotNull(helpers);
|
|
Assert.Equal(2, helpers.Length);
|
|
|
|
var propAHelper = Assert.Single(helpers.Where(h => h.Name == "PropA"));
|
|
var propBHelper = Assert.Single(helpers.Where(h => h.Name == "PropB"));
|
|
|
|
Assert.Equal("propAValue", propAHelper.GetValue(derived));
|
|
Assert.Equal("Newed", propBHelper.GetValue(derived));
|
|
}
|
|
|
|
[Fact]
|
|
public void PropertyHelper_ForDerived_WithVirtual()
|
|
{
|
|
// Arrange
|
|
var derived = new DerivedClassWithOverride { PropA = "propAValue", PropB = "propBValue" };
|
|
|
|
// Act
|
|
var helpers = PropertyHelper.GetProperties(derived.GetType().GetTypeInfo()).ToArray();
|
|
|
|
// Assert
|
|
Assert.NotNull(helpers);
|
|
Assert.Equal(2, helpers.Length);
|
|
|
|
var propAHelper = Assert.Single(helpers.Where(h => h.Name == "PropA"));
|
|
var propBHelper = Assert.Single(helpers.Where(h => h.Name == "PropB"));
|
|
|
|
Assert.Equal("OverridenpropAValue", propAHelper.GetValue(derived));
|
|
Assert.Equal("propBValue", propBHelper.GetValue(derived));
|
|
}
|
|
|
|
[Fact]
|
|
public void PropertyHelper_ForInterface_ReturnsExpectedProperties()
|
|
{
|
|
// Arrange
|
|
var expectedNames = new[] { "Count", "IsReadOnly" };
|
|
|
|
// Act
|
|
var helpers = PropertyHelper.GetProperties(typeof(ICollection<string>));
|
|
|
|
// Assert
|
|
Assert.Collection(
|
|
helpers.OrderBy(helper => helper.Name, StringComparer.Ordinal),
|
|
helper => { Assert.Equal(expectedNames[0], helper.Name, StringComparer.Ordinal); },
|
|
helper => { Assert.Equal(expectedNames[1], helper.Name, StringComparer.Ordinal); });
|
|
}
|
|
|
|
[Fact]
|
|
public void PropertyHelper_ForDerivedInterface_ReturnsAllProperties()
|
|
{
|
|
// Arrange
|
|
var expectedNames = new[] { "Count", "IsReadOnly", "Keys", "Values" };
|
|
|
|
// Act
|
|
var helpers = PropertyHelper.GetProperties(typeof(IDictionary<string, string>));
|
|
|
|
// Assert
|
|
Assert.Collection(
|
|
helpers.OrderBy(helper => helper.Name, StringComparer.Ordinal),
|
|
helper => { Assert.Equal(expectedNames[0], helper.Name, StringComparer.Ordinal); },
|
|
helper => { Assert.Equal(expectedNames[1], helper.Name, StringComparer.Ordinal); },
|
|
helper => { Assert.Equal(expectedNames[2], helper.Name, StringComparer.Ordinal); },
|
|
helper => { Assert.Equal(expectedNames[3], helper.Name, StringComparer.Ordinal); });
|
|
}
|
|
|
|
[Fact]
|
|
public void GetProperties_ExcludesIndexersAndPropertiesWithoutPublicGetters()
|
|
{
|
|
// Arrange
|
|
var type = typeof(DerivedClassWithNonReadableProperties);
|
|
|
|
// Act
|
|
var result = PropertyHelper.GetProperties(type).ToArray();
|
|
|
|
// Assert
|
|
Assert.Equal(3, result.Length);
|
|
Assert.Equal("Visible", result[0].Name);
|
|
Assert.Equal("PropA", result[1].Name);
|
|
Assert.Equal("PropB", result[2].Name);
|
|
}
|
|
|
|
[Fact]
|
|
public void GetVisibleProperties_NoHiddenProperty()
|
|
{
|
|
// Arrange
|
|
var type = typeof(string);
|
|
|
|
// Act
|
|
var result = PropertyHelper.GetVisibleProperties(type).ToArray();
|
|
|
|
// Assert
|
|
var property = Assert.Single(result);
|
|
Assert.Equal("Length", property.Name);
|
|
Assert.Equal(typeof(int), property.Property.PropertyType);
|
|
}
|
|
|
|
[Fact]
|
|
public void GetVisibleProperties_HiddenProperty()
|
|
{
|
|
// Arrange
|
|
var type = typeof(DerivedHiddenProperty);
|
|
|
|
// Act
|
|
var result = PropertyHelper.GetVisibleProperties(type).ToArray();
|
|
|
|
// Assert
|
|
Assert.Equal(2, result.Length);
|
|
Assert.Equal("Id", result[0].Name);
|
|
Assert.Equal(typeof(string), result[0].Property.PropertyType);
|
|
Assert.Equal("Name", result[1].Name);
|
|
Assert.Equal(typeof(string), result[1].Property.PropertyType);
|
|
}
|
|
|
|
[Fact]
|
|
public void GetVisibleProperties_HiddenProperty_TwoLevels()
|
|
{
|
|
// Arrange
|
|
var type = typeof(DerivedHiddenProperty2);
|
|
|
|
// Act
|
|
var result = PropertyHelper.GetVisibleProperties(type).ToArray();
|
|
|
|
// Assert
|
|
Assert.Equal(2, result.Length);
|
|
Assert.Equal("Id", result[0].Name);
|
|
Assert.Equal(typeof(Guid), result[0].Property.PropertyType);
|
|
Assert.Equal("Name", result[1].Name);
|
|
Assert.Equal(typeof(string), result[1].Property.PropertyType);
|
|
}
|
|
|
|
[Fact]
|
|
public void GetVisibleProperties_NoHiddenPropertyWithTypeInfoInput()
|
|
{
|
|
// Arrange
|
|
var type = typeof(string);
|
|
|
|
// Act
|
|
var result = PropertyHelper.GetVisibleProperties(type.GetTypeInfo()).ToArray();
|
|
|
|
// Assert
|
|
var property = Assert.Single(result);
|
|
Assert.Equal("Length", property.Name);
|
|
Assert.Equal(typeof(int), property.Property.PropertyType);
|
|
}
|
|
|
|
[Fact]
|
|
public void GetVisibleProperties_HiddenPropertyWithTypeInfoInput()
|
|
{
|
|
// Arrange
|
|
var type = typeof(DerivedHiddenProperty);
|
|
|
|
// Act
|
|
var result = PropertyHelper.GetVisibleProperties(type.GetTypeInfo()).ToArray();
|
|
|
|
// Assert
|
|
Assert.Equal(2, result.Length);
|
|
Assert.Equal("Id", result[0].Name);
|
|
Assert.Equal(typeof(string), result[0].Property.PropertyType);
|
|
Assert.Equal("Name", result[1].Name);
|
|
Assert.Equal(typeof(string), result[1].Property.PropertyType);
|
|
}
|
|
|
|
[Fact]
|
|
public void GetVisibleProperties_HiddenProperty_TwoLevelsWithTypeInfoInput()
|
|
{
|
|
// Arrange
|
|
var type = typeof(DerivedHiddenProperty2);
|
|
|
|
// Act
|
|
var result = PropertyHelper.GetVisibleProperties(type.GetTypeInfo()).ToArray();
|
|
|
|
// Assert
|
|
Assert.Equal(2, result.Length);
|
|
Assert.Equal("Id", result[0].Name);
|
|
Assert.Equal(typeof(Guid), result[0].Property.PropertyType);
|
|
Assert.Equal("Name", result[1].Name);
|
|
Assert.Equal(typeof(string), result[1].Property.PropertyType);
|
|
}
|
|
|
|
[Fact]
|
|
public void MakeFastPropertySetter_SetsPropertyValues_ForPublicAndNobPublicProperties()
|
|
{
|
|
// Arrange
|
|
var instance = new BaseClass();
|
|
var typeInfo = instance.GetType().GetTypeInfo();
|
|
var publicProperty = typeInfo.GetDeclaredProperty("PropA");
|
|
var protectedProperty = typeInfo.GetDeclaredProperty("PropProtected");
|
|
var publicPropertySetter = PropertyHelper.MakeFastPropertySetter(publicProperty);
|
|
var protectedPropertySetter = PropertyHelper.MakeFastPropertySetter(protectedProperty);
|
|
|
|
// Act
|
|
publicPropertySetter(instance, "TestPublic");
|
|
protectedPropertySetter(instance, "TestProtected");
|
|
|
|
// Assert
|
|
Assert.Equal("TestPublic", instance.PropA);
|
|
Assert.Equal("TestProtected", instance.GetPropProtected());
|
|
}
|
|
|
|
[Fact]
|
|
public void MakeFastPropertySetter_SetsPropertyValues_ForOverridenProperties()
|
|
{
|
|
// Arrange
|
|
var instance = new DerivedClassWithOverride();
|
|
var typeInfo = instance.GetType().GetTypeInfo();
|
|
var property = typeInfo.GetDeclaredProperty("PropA");
|
|
var propertySetter = PropertyHelper.MakeFastPropertySetter(property);
|
|
|
|
// Act
|
|
propertySetter(instance, "Test value");
|
|
|
|
// Assert
|
|
Assert.Equal("OverridenTest value", instance.PropA);
|
|
}
|
|
|
|
[Fact]
|
|
public void MakeFastPropertySetter_SetsPropertyValues_ForNewedProperties()
|
|
{
|
|
// Arrange
|
|
var instance = new DerivedClassWithNew();
|
|
var typeInfo = instance.GetType().GetTypeInfo();
|
|
var property = typeInfo.GetDeclaredProperty("PropB");
|
|
var propertySetter = PropertyHelper.MakeFastPropertySetter(property);
|
|
|
|
// Act
|
|
propertySetter(instance, "Test value");
|
|
|
|
// Assert
|
|
Assert.Equal("NewedTest value", instance.PropB);
|
|
}
|
|
|
|
[Fact]
|
|
public void MakeFastPropertyGetter_ReferenceType_ForNullObject_Throws()
|
|
{
|
|
// Arrange
|
|
var property = PropertyHelper
|
|
.GetProperties(typeof(BaseClass))
|
|
.Single(p => p.Name == nameof(BaseClass.PropA));
|
|
|
|
var accessor = PropertyHelper.MakeFastPropertyGetter(property.Property);
|
|
|
|
// Act & Assert
|
|
Assert.Throws<NullReferenceException>(() => accessor(null));
|
|
}
|
|
|
|
[Fact]
|
|
public void MakeFastPropertyGetter_ValueType_ForNullObject_Throws()
|
|
{
|
|
// Arrange
|
|
var property = PropertyHelper
|
|
.GetProperties(typeof(MyProperties))
|
|
.Single(p => p.Name == nameof(MyProperties.StringProp));
|
|
|
|
var accessor = PropertyHelper.MakeFastPropertyGetter(property.Property);
|
|
|
|
// Act & Assert
|
|
Assert.Throws<NullReferenceException>(() => accessor(null));
|
|
}
|
|
|
|
[Fact]
|
|
public void MakeNullSafeFastPropertyGetter_ReferenceType_Success()
|
|
{
|
|
// Arrange
|
|
var property = PropertyHelper
|
|
.GetProperties(typeof(BaseClass))
|
|
.Single(p => p.Name == nameof(BaseClass.PropA));
|
|
|
|
var accessor = PropertyHelper.MakeNullSafeFastPropertyGetter(property.Property);
|
|
|
|
// Act
|
|
var value = accessor(new BaseClass() { PropA = "Hi" });
|
|
|
|
// Assert
|
|
Assert.Equal("Hi", value);
|
|
}
|
|
|
|
[Fact]
|
|
public void MakeNullSafeFastPropertyGetter_ValueType_Success()
|
|
{
|
|
// Arrange
|
|
var property = PropertyHelper
|
|
.GetProperties(typeof(MyProperties))
|
|
.Single(p => p.Name == nameof(MyProperties.StringProp));
|
|
|
|
var accessor = PropertyHelper.MakeNullSafeFastPropertyGetter(property.Property);
|
|
|
|
// Act
|
|
var value = accessor(new MyProperties() { StringProp = "Hi" });
|
|
|
|
// Assert
|
|
Assert.Equal("Hi", value);
|
|
}
|
|
|
|
[Fact]
|
|
public void MakeNullSafeFastPropertyGetter_ReferenceType_ForNullObject_ReturnsNull()
|
|
{
|
|
// Arrange
|
|
var property = PropertyHelper
|
|
.GetProperties(typeof(BaseClass))
|
|
.Single(p => p.Name == nameof(BaseClass.PropA));
|
|
|
|
var accessor = PropertyHelper.MakeNullSafeFastPropertyGetter(property.Property);
|
|
|
|
// Act
|
|
var value = accessor(null);
|
|
|
|
// Assert
|
|
Assert.Null(value);
|
|
}
|
|
|
|
[Fact]
|
|
public void MakeNullSafeFastPropertyGetter_ValueType_ForNullObject_ReturnsNull()
|
|
{
|
|
// Arrange
|
|
var property = PropertyHelper
|
|
.GetProperties(typeof(MyProperties))
|
|
.Single(p => p.Name == nameof(MyProperties.StringProp));
|
|
|
|
var accessor = PropertyHelper.MakeNullSafeFastPropertyGetter(property.Property);
|
|
|
|
// Act
|
|
var value = accessor(null);
|
|
|
|
// Assert
|
|
Assert.Null(value);
|
|
}
|
|
|
|
public static TheoryData<object, KeyValuePair<string, object>> IgnoreCaseTestData
|
|
{
|
|
get
|
|
{
|
|
return new TheoryData<object, KeyValuePair<string, object>>
|
|
{
|
|
{
|
|
new
|
|
{
|
|
selected = true,
|
|
SeLeCtEd = false
|
|
},
|
|
new KeyValuePair<string, object>("selected", false)
|
|
},
|
|
{
|
|
new
|
|
{
|
|
SeLeCtEd = false,
|
|
selected = true
|
|
},
|
|
new KeyValuePair<string, object>("SeLeCtEd", true)
|
|
},
|
|
{
|
|
new
|
|
{
|
|
SelECTeD = false,
|
|
SeLECTED = true
|
|
},
|
|
new KeyValuePair<string, object>("SelECTeD", true)
|
|
}
|
|
};
|
|
}
|
|
}
|
|
|
|
[Theory]
|
|
[MemberData(nameof(IgnoreCaseTestData))]
|
|
public void ObjectToDictionary_IgnoresPropertyCase(object testObject,
|
|
KeyValuePair<string, object> expectedEntry)
|
|
{
|
|
// Act
|
|
var result = PropertyHelper.ObjectToDictionary(testObject);
|
|
|
|
// Assert
|
|
var entry = Assert.Single(result);
|
|
Assert.Equal(expectedEntry, entry);
|
|
}
|
|
|
|
[Fact]
|
|
public void ObjectToDictionary_WithNullObject_ReturnsEmptyDictionary()
|
|
{
|
|
// Arrange
|
|
object value = null;
|
|
|
|
// Act
|
|
var dictValues = PropertyHelper.ObjectToDictionary(value);
|
|
|
|
// Assert
|
|
Assert.NotNull(dictValues);
|
|
Assert.Equal(0, dictValues.Count);
|
|
}
|
|
|
|
[Fact]
|
|
public void ObjectToDictionary_WithPlainObjectType_ReturnsEmptyDictionary()
|
|
{
|
|
// Arrange
|
|
var value = new object();
|
|
|
|
// Act
|
|
var dictValues = PropertyHelper.ObjectToDictionary(value);
|
|
|
|
// Assert
|
|
Assert.NotNull(dictValues);
|
|
Assert.Equal(0, dictValues.Count);
|
|
}
|
|
|
|
[Fact]
|
|
public void ObjectToDictionary_WithPrimitiveType_LooksUpPublicProperties()
|
|
{
|
|
// Arrange
|
|
var value = "test";
|
|
|
|
// Act
|
|
var dictValues = PropertyHelper.ObjectToDictionary(value);
|
|
|
|
// Assert
|
|
Assert.NotNull(dictValues);
|
|
Assert.Equal(1, dictValues.Count);
|
|
Assert.Equal(4, dictValues["Length"]);
|
|
}
|
|
|
|
[Fact]
|
|
public void ObjectToDictionary_WithAnonymousType_LooksUpProperties()
|
|
{
|
|
// Arrange
|
|
var value = new { test = "value", other = 1 };
|
|
|
|
// Act
|
|
var dictValues = PropertyHelper.ObjectToDictionary(value);
|
|
|
|
// Assert
|
|
Assert.NotNull(dictValues);
|
|
Assert.Equal(2, dictValues.Count);
|
|
Assert.Equal("value", dictValues["test"]);
|
|
Assert.Equal(1, dictValues["other"]);
|
|
}
|
|
|
|
[Fact]
|
|
public void ObjectToDictionary_ReturnsCaseInsensitiveDictionary()
|
|
{
|
|
// Arrange
|
|
var value = new { TEST = "value", oThEr = 1 };
|
|
|
|
// Act
|
|
var dictValues = PropertyHelper.ObjectToDictionary(value);
|
|
|
|
// Assert
|
|
Assert.NotNull(dictValues);
|
|
Assert.Equal(2, dictValues.Count);
|
|
Assert.Equal("value", dictValues["test"]);
|
|
Assert.Equal(1, dictValues["other"]);
|
|
}
|
|
|
|
[Fact]
|
|
public void ObjectToDictionary_ReturnsInheritedProperties()
|
|
{
|
|
// Arrange
|
|
var value = new ThreeDPoint() { X = 5, Y = 10, Z = 17 };
|
|
|
|
// Act
|
|
var dictValues = PropertyHelper.ObjectToDictionary(value);
|
|
|
|
// Assert
|
|
Assert.NotNull(dictValues);
|
|
Assert.Equal(3, dictValues.Count);
|
|
Assert.Equal(5, dictValues["X"]);
|
|
Assert.Equal(10, dictValues["Y"]);
|
|
Assert.Equal(17, dictValues["Z"]);
|
|
}
|
|
|
|
private class Point
|
|
{
|
|
public int X { get; set; }
|
|
public int Y { get; set; }
|
|
}
|
|
|
|
private class ThreeDPoint : Point
|
|
{
|
|
public int Z { get; set; }
|
|
}
|
|
|
|
private class Static
|
|
{
|
|
public static int Prop2 { get; set; }
|
|
public int Prop5 { get; set; }
|
|
}
|
|
|
|
#if NETSTANDARD || NETCOREAPP
|
|
private class RefStructProperties
|
|
{
|
|
public Span<bool> Span => throw new NotImplementedException();
|
|
public MyRefStruct UserDefined => throw new NotImplementedException();
|
|
|
|
public int Prop5 { get; set; }
|
|
}
|
|
|
|
private readonly ref struct MyRefStruct
|
|
{
|
|
}
|
|
#elif NET46 || NET461
|
|
#else
|
|
#error Unknown TFM - update the set of TFMs where we test for ref structs
|
|
#endif
|
|
private struct MyProperties
|
|
{
|
|
public int IntProp { get; set; }
|
|
public string StringProp { get; set; }
|
|
}
|
|
|
|
private class SetOnly
|
|
{
|
|
public int Prop2 { set { } }
|
|
public int Prop6 { get; set; }
|
|
}
|
|
|
|
private class PrivateProperties
|
|
{
|
|
public int Prop1 { get; set; }
|
|
protected int Prop2 { get; set; }
|
|
private int Prop3 { get; set; }
|
|
}
|
|
|
|
public class BaseClass
|
|
{
|
|
public string PropA { get; set; }
|
|
|
|
protected string PropProtected { get; set; }
|
|
|
|
public string GetPropProtected()
|
|
{
|
|
return PropProtected;
|
|
}
|
|
}
|
|
|
|
public class DerivedClass : BaseClass
|
|
{
|
|
public string PropB { get; set; }
|
|
}
|
|
|
|
public class BaseClassWithVirtual
|
|
{
|
|
public virtual string PropA { get; set; }
|
|
public string PropB { get; set; }
|
|
}
|
|
|
|
public class DerivedClassWithNew : BaseClassWithVirtual
|
|
{
|
|
private string _value = "Newed";
|
|
|
|
public new string PropB
|
|
{
|
|
get { return _value; }
|
|
set { _value = "Newed" + value; }
|
|
}
|
|
}
|
|
|
|
public class DerivedClassWithOverride : BaseClassWithVirtual
|
|
{
|
|
private string _value = "Overriden";
|
|
|
|
public override string PropA
|
|
{
|
|
get { return _value; }
|
|
set { _value = "Overriden" + value; }
|
|
}
|
|
}
|
|
|
|
private class DerivedClassWithNonReadableProperties : BaseClassWithVirtual
|
|
{
|
|
public string this[int index]
|
|
{
|
|
get { return string.Empty; }
|
|
set { }
|
|
}
|
|
|
|
public int Visible { get; set; }
|
|
|
|
private string NotVisible { get; set; }
|
|
|
|
public string NotVisible2 { private get; set; }
|
|
|
|
public string NotVisible3
|
|
{
|
|
set { }
|
|
}
|
|
|
|
public static string NotVisible4 { get; set; }
|
|
}
|
|
|
|
private struct MyStruct
|
|
{
|
|
public string Foo { get; set; }
|
|
}
|
|
|
|
private class BaseHiddenProperty
|
|
{
|
|
public int Id { get; set; }
|
|
}
|
|
|
|
private class DerivedHiddenProperty : BaseHiddenProperty
|
|
{
|
|
public new string Id { get; set; }
|
|
|
|
public string Name { get; set; }
|
|
}
|
|
|
|
private class DerivedHiddenProperty2 : DerivedHiddenProperty
|
|
{
|
|
public new Guid Id { get; set; }
|
|
|
|
public new string Name { get; private set; }
|
|
}
|
|
}
|
|
}
|