From 03c48d753efa16255bfc1892cd649b50969472df Mon Sep 17 00:00:00 2001
From: Ferdinando Papale <4850119+papafe@users.noreply.github.com>
Date: Fri, 9 Feb 2024 12:56:18 +0100
Subject: [PATCH 01/10] Added support for expressions in keypath building
---
.../Realm/DatabaseTypes/KeyPathCollection.cs | 51 +++++++++++++++++
.../Realm.Tests/Database/NotificationTests.cs | 33 +++++++++++
.../DeepObject1_generated.cs | 56 ++++++++++++++++++-
.../DeepObject2_generated.cs | 56 ++++++++++++++++++-
.../DeepObject3_generated.cs | 56 ++++++++++++++++++-
.../DeepObject4_generated.cs | 56 ++++++++++++++++++-
.../DeepObject5_generated.cs | 52 ++++++++++++++++-
.../TestNotificationObject_generated.cs | 23 ++++++++
8 files changed, 373 insertions(+), 10 deletions(-)
diff --git a/Realm/Realm/DatabaseTypes/KeyPathCollection.cs b/Realm/Realm/DatabaseTypes/KeyPathCollection.cs
index d33aef4f93..9fa8f9a42d 100644
--- a/Realm/Realm/DatabaseTypes/KeyPathCollection.cs
+++ b/Realm/Realm/DatabaseTypes/KeyPathCollection.cs
@@ -21,6 +21,7 @@
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
+using System.Linq.Expressions;
namespace Realms;
@@ -78,6 +79,19 @@ public static KeyPathsCollection Of(params KeyPath[] paths)
return new KeyPathsCollection(KeyPathsCollectionType.Explicit, paths);
}
+ ///
+ /// Builds a from an array of .
+ /// Each of the expressions must represent the path to a realm object property, eventually chained.
+ ///
+ /// The realm object. type.
+ /// The array of to use for the .
+ /// The built from the input array of .
+ public static KeyPathsCollection Of(params Expression>[] expressions)
+ where T : IRealmObject
+ {
+ return Of(expressions.Select(KeyPath.For).ToArray());
+ }
+
///
/// Gets a value for shallow notifications, that will raise notifications only for changes to the collection itself (for example when an element is added or removed),
/// but not for changes to any of the properties of the elements of the collection.
@@ -125,10 +139,14 @@ IEnumerator IEnumerable.GetEnumerator()
}
}
+//TODO Fix changelog
+
///
/// Represents a key path that can be used as a part of a when subscribing for notifications.
/// A can be implicitly built from a string, where the string is the name of a property (e.g "FirstName"), eventually dotted to indicated nested properties.
/// (e.g "Dog.Name"). Wildcards can also be used in key paths to capture all properties at a given level (e.g "*", "Friends.*" or "*.FirstName").
+/// A can also be built using the method, that creates the corresponding
+/// to the property path represented by the input expression.
///
public readonly struct KeyPath
{
@@ -139,8 +157,41 @@ private KeyPath(string path)
Path = path;
}
+ ///
+ /// Creates a from a lambda expression that specifies a property path for a given realm object type.
+ ///
+ /// The type of the realm object..
+ /// The expression specifying the path to the property.
+ /// A representing the full path to the specified property.
+ ///
+ ///
+ /// var keyPath = KeyPath.For<Person>(p => p.Dog.Name);
+ ///
+ ///
+ public static KeyPath For(Expression> expression)
+ where T : IRealmObject
+ {
+ return new KeyPath(GetFullPath(expression.Body));
+ }
+
public static implicit operator KeyPath(string s) => new(s);
+ private static string GetFullPath(Expression expression)
+ {
+ if (expression is MemberExpression memberExpression)
+ {
+ var subPath = GetFullPath(memberExpression.Expression);
+ return string.IsNullOrEmpty(subPath) ? memberExpression.Member.Name : $"{subPath}.{memberExpression.Member.Name}";
+ }
+ else if (expression is ParameterExpression)
+ {
+ // This is the parameter of the expression, nothing to add
+ return string.Empty;
+ }
+
+ throw new Exception();
+ }
+
///
public override bool Equals(object? obj) => obj is KeyPath path && Path == path.Path;
diff --git a/Tests/Realm.Tests/Database/NotificationTests.cs b/Tests/Realm.Tests/Database/NotificationTests.cs
index 7a75955ebe..22dda2007d 100644
--- a/Tests/Realm.Tests/Database/NotificationTests.cs
+++ b/Tests/Realm.Tests/Database/NotificationTests.cs
@@ -1654,6 +1654,18 @@ public void KeyPath_ImplicitOperator_CorrectlyConvertsFromString()
Assert.That(keyPath.Path, Is.EqualTo("test"));
}
+ [Test]
+ public void KeyPath_CanBeBuiltFromExpressions()
+ {
+ KeyPath keyPath;
+
+ keyPath = KeyPath.For(t => t.ListSameType);
+ Assert.That(keyPath.Path, Is.EqualTo("ListSameType"));
+
+ keyPath = KeyPath.For(t => t.LinkAnotherType!.DictOfDogs);
+ Assert.That(keyPath.Path, Is.EqualTo("LinkAnotherType.DictOfDogs"));
+ }
+
[Test]
public void KeyPathsCollection_CanBeBuiltInDifferentWays()
{
@@ -1710,6 +1722,27 @@ void AssertKeyPathsCollectionCorrectness(KeyPathsCollection k, IEnumerable { "ListSameType", "LinkAnotherType.DictOfDogs" };
+
+ kpc = KeyPathsCollection.Of(t => t.ListSameType, t => t.LinkAnotherType!.DictOfDogs);
+ AssertKeyPathsCollectionCorrectness(kpc, expected);
+
+ kpc = KeyPathsCollection.Of(KeyPath.For(t => t.ListSameType),
+ KeyPath.For(t => t.LinkAnotherType!.DictOfDogs));
+ AssertKeyPathsCollectionCorrectness(kpc, expected);
+
+ void AssertKeyPathsCollectionCorrectness(KeyPathsCollection k, IEnumerable expected)
+ {
+ Assert.That(k.Type, Is.EqualTo(KeyPathsCollectionType.Explicit));
+ Assert.That(k.GetStrings(), Is.EqualTo(expected));
+ }
+ }
+
[Test]
public void SubscribeWithKeypaths_AnyKeypath_RaisesNotificationsForResults()
{
diff --git a/Tests/Realm.Tests/Generated/Realm.SourceGenerator/Realms.SourceGenerator.RealmGenerator/DeepObject1_generated.cs b/Tests/Realm.Tests/Generated/Realm.SourceGenerator/Realms.SourceGenerator.RealmGenerator/DeepObject1_generated.cs
index ce4427b07e..40a88b97d8 100644
--- a/Tests/Realm.Tests/Generated/Realm.SourceGenerator/Realms.SourceGenerator.RealmGenerator/DeepObject1_generated.cs
+++ b/Tests/Realm.Tests/Generated/Realm.SourceGenerator/Realms.SourceGenerator.RealmGenerator/DeepObject1_generated.cs
@@ -1,6 +1,7 @@
//
#nullable enable
+using MongoDB.Bson.Serialization;
using NUnit.Framework;
using Realms;
using Realms.Logging;
@@ -26,6 +27,13 @@ namespace Realms.Tests.Database
[Woven(typeof(DeepObject1ObjectHelper)), Realms.Preserve(AllMembers = true)]
public partial class DeepObject1 : IRealmObject, INotifyPropertyChanged, IReflectableType
{
+
+ [Realms.Preserve]
+ static DeepObject1()
+ {
+ Realms.Serialization.RealmObjectSerializer.Register(new DeepObject1Serializer());
+ }
+
///
/// Defines the schema for the class.
///
@@ -266,7 +274,7 @@ internal interface IDeepObject1Accessor : Realms.IRealmAccessor
}
[EditorBrowsable(EditorBrowsableState.Never), Realms.Preserve(AllMembers = true)]
- internal class DeepObject1ManagedAccessor : Realms.ManagedAccessor, IDeepObject1Accessor
+ private class DeepObject1ManagedAccessor : Realms.ManagedAccessor, IDeepObject1Accessor
{
public string? StringValue
{
@@ -282,7 +290,7 @@ public Realms.Tests.Database.DeepObject2? RecursiveObject
}
[EditorBrowsable(EditorBrowsableState.Never), Realms.Preserve(AllMembers = true)]
- internal class DeepObject1UnmanagedAccessor : Realms.UnmanagedAccessor, IDeepObject1Accessor
+ private class DeepObject1UnmanagedAccessor : Realms.UnmanagedAccessor, IDeepObject1Accessor
{
public override ObjectSchema ObjectSchema => DeepObject1.RealmSchema;
@@ -357,5 +365,49 @@ public override IDictionary GetDictionaryValue(string pr
throw new MissingMemberException($"The object does not have a Realm dictionary property with name {propertyName}");
}
}
+
+ [EditorBrowsable(EditorBrowsableState.Never), Realms.Preserve(AllMembers = true)]
+ private class DeepObject1Serializer : Realms.Serialization.RealmObjectSerializerBase
+ {
+ public override string SchemaName => "DeepObject1";
+
+ protected override void SerializeValue(MongoDB.Bson.Serialization.BsonSerializationContext context, BsonSerializationArgs args, DeepObject1 value)
+ {
+ context.Writer.WriteStartDocument();
+
+ WriteValue(context, args, "StringValue", value.StringValue);
+ WriteValue(context, args, "RecursiveObject", value.RecursiveObject);
+
+ context.Writer.WriteEndDocument();
+ }
+
+ protected override DeepObject1 CreateInstance() => new DeepObject1();
+
+ protected override void ReadValue(DeepObject1 instance, string name, BsonDeserializationContext context)
+ {
+ switch (name)
+ {
+ case "StringValue":
+ instance.StringValue = BsonSerializer.LookupSerializer().Deserialize(context);
+ break;
+ case "RecursiveObject":
+ instance.RecursiveObject = Realms.Serialization.RealmObjectSerializer.LookupSerializer()!.DeserializeById(context);
+ break;
+ default:
+ context.Reader.SkipValue();
+ break;
+ }
+ }
+
+ protected override void ReadArrayElement(DeepObject1 instance, string name, BsonDeserializationContext context)
+ {
+ // No persisted list/set properties to deserialize
+ }
+
+ protected override void ReadDocumentField(DeepObject1 instance, string name, string fieldName, BsonDeserializationContext context)
+ {
+ // No persisted dictionary properties to deserialize
+ }
+ }
}
}
diff --git a/Tests/Realm.Tests/Generated/Realm.SourceGenerator/Realms.SourceGenerator.RealmGenerator/DeepObject2_generated.cs b/Tests/Realm.Tests/Generated/Realm.SourceGenerator/Realms.SourceGenerator.RealmGenerator/DeepObject2_generated.cs
index babdbb7bd9..d97dccd7d1 100644
--- a/Tests/Realm.Tests/Generated/Realm.SourceGenerator/Realms.SourceGenerator.RealmGenerator/DeepObject2_generated.cs
+++ b/Tests/Realm.Tests/Generated/Realm.SourceGenerator/Realms.SourceGenerator.RealmGenerator/DeepObject2_generated.cs
@@ -1,6 +1,7 @@
//
#nullable enable
+using MongoDB.Bson.Serialization;
using NUnit.Framework;
using Realms;
using Realms.Logging;
@@ -26,6 +27,13 @@ namespace Realms.Tests.Database
[Woven(typeof(DeepObject2ObjectHelper)), Realms.Preserve(AllMembers = true)]
public partial class DeepObject2 : IRealmObject, INotifyPropertyChanged, IReflectableType
{
+
+ [Realms.Preserve]
+ static DeepObject2()
+ {
+ Realms.Serialization.RealmObjectSerializer.Register(new DeepObject2Serializer());
+ }
+
///
/// Defines the schema for the class.
///
@@ -266,7 +274,7 @@ internal interface IDeepObject2Accessor : Realms.IRealmAccessor
}
[EditorBrowsable(EditorBrowsableState.Never), Realms.Preserve(AllMembers = true)]
- internal class DeepObject2ManagedAccessor : Realms.ManagedAccessor, IDeepObject2Accessor
+ private class DeepObject2ManagedAccessor : Realms.ManagedAccessor, IDeepObject2Accessor
{
public string? StringValue
{
@@ -282,7 +290,7 @@ public Realms.Tests.Database.DeepObject3? RecursiveObject
}
[EditorBrowsable(EditorBrowsableState.Never), Realms.Preserve(AllMembers = true)]
- internal class DeepObject2UnmanagedAccessor : Realms.UnmanagedAccessor, IDeepObject2Accessor
+ private class DeepObject2UnmanagedAccessor : Realms.UnmanagedAccessor, IDeepObject2Accessor
{
public override ObjectSchema ObjectSchema => DeepObject2.RealmSchema;
@@ -357,5 +365,49 @@ public override IDictionary GetDictionaryValue(string pr
throw new MissingMemberException($"The object does not have a Realm dictionary property with name {propertyName}");
}
}
+
+ [EditorBrowsable(EditorBrowsableState.Never), Realms.Preserve(AllMembers = true)]
+ private class DeepObject2Serializer : Realms.Serialization.RealmObjectSerializerBase
+ {
+ public override string SchemaName => "DeepObject2";
+
+ protected override void SerializeValue(MongoDB.Bson.Serialization.BsonSerializationContext context, BsonSerializationArgs args, DeepObject2 value)
+ {
+ context.Writer.WriteStartDocument();
+
+ WriteValue(context, args, "StringValue", value.StringValue);
+ WriteValue(context, args, "RecursiveObject", value.RecursiveObject);
+
+ context.Writer.WriteEndDocument();
+ }
+
+ protected override DeepObject2 CreateInstance() => new DeepObject2();
+
+ protected override void ReadValue(DeepObject2 instance, string name, BsonDeserializationContext context)
+ {
+ switch (name)
+ {
+ case "StringValue":
+ instance.StringValue = BsonSerializer.LookupSerializer().Deserialize(context);
+ break;
+ case "RecursiveObject":
+ instance.RecursiveObject = Realms.Serialization.RealmObjectSerializer.LookupSerializer()!.DeserializeById(context);
+ break;
+ default:
+ context.Reader.SkipValue();
+ break;
+ }
+ }
+
+ protected override void ReadArrayElement(DeepObject2 instance, string name, BsonDeserializationContext context)
+ {
+ // No persisted list/set properties to deserialize
+ }
+
+ protected override void ReadDocumentField(DeepObject2 instance, string name, string fieldName, BsonDeserializationContext context)
+ {
+ // No persisted dictionary properties to deserialize
+ }
+ }
}
}
diff --git a/Tests/Realm.Tests/Generated/Realm.SourceGenerator/Realms.SourceGenerator.RealmGenerator/DeepObject3_generated.cs b/Tests/Realm.Tests/Generated/Realm.SourceGenerator/Realms.SourceGenerator.RealmGenerator/DeepObject3_generated.cs
index 8207c59534..e252614c41 100644
--- a/Tests/Realm.Tests/Generated/Realm.SourceGenerator/Realms.SourceGenerator.RealmGenerator/DeepObject3_generated.cs
+++ b/Tests/Realm.Tests/Generated/Realm.SourceGenerator/Realms.SourceGenerator.RealmGenerator/DeepObject3_generated.cs
@@ -1,6 +1,7 @@
//
#nullable enable
+using MongoDB.Bson.Serialization;
using NUnit.Framework;
using Realms;
using Realms.Logging;
@@ -26,6 +27,13 @@ namespace Realms.Tests.Database
[Woven(typeof(DeepObject3ObjectHelper)), Realms.Preserve(AllMembers = true)]
public partial class DeepObject3 : IRealmObject, INotifyPropertyChanged, IReflectableType
{
+
+ [Realms.Preserve]
+ static DeepObject3()
+ {
+ Realms.Serialization.RealmObjectSerializer.Register(new DeepObject3Serializer());
+ }
+
///
/// Defines the schema for the class.
///
@@ -266,7 +274,7 @@ internal interface IDeepObject3Accessor : Realms.IRealmAccessor
}
[EditorBrowsable(EditorBrowsableState.Never), Realms.Preserve(AllMembers = true)]
- internal class DeepObject3ManagedAccessor : Realms.ManagedAccessor, IDeepObject3Accessor
+ private class DeepObject3ManagedAccessor : Realms.ManagedAccessor, IDeepObject3Accessor
{
public string? StringValue
{
@@ -282,7 +290,7 @@ public Realms.Tests.Database.DeepObject4? RecursiveObject
}
[EditorBrowsable(EditorBrowsableState.Never), Realms.Preserve(AllMembers = true)]
- internal class DeepObject3UnmanagedAccessor : Realms.UnmanagedAccessor, IDeepObject3Accessor
+ private class DeepObject3UnmanagedAccessor : Realms.UnmanagedAccessor, IDeepObject3Accessor
{
public override ObjectSchema ObjectSchema => DeepObject3.RealmSchema;
@@ -357,5 +365,49 @@ public override IDictionary GetDictionaryValue(string pr
throw new MissingMemberException($"The object does not have a Realm dictionary property with name {propertyName}");
}
}
+
+ [EditorBrowsable(EditorBrowsableState.Never), Realms.Preserve(AllMembers = true)]
+ private class DeepObject3Serializer : Realms.Serialization.RealmObjectSerializerBase
+ {
+ public override string SchemaName => "DeepObject3";
+
+ protected override void SerializeValue(MongoDB.Bson.Serialization.BsonSerializationContext context, BsonSerializationArgs args, DeepObject3 value)
+ {
+ context.Writer.WriteStartDocument();
+
+ WriteValue(context, args, "StringValue", value.StringValue);
+ WriteValue(context, args, "RecursiveObject", value.RecursiveObject);
+
+ context.Writer.WriteEndDocument();
+ }
+
+ protected override DeepObject3 CreateInstance() => new DeepObject3();
+
+ protected override void ReadValue(DeepObject3 instance, string name, BsonDeserializationContext context)
+ {
+ switch (name)
+ {
+ case "StringValue":
+ instance.StringValue = BsonSerializer.LookupSerializer().Deserialize(context);
+ break;
+ case "RecursiveObject":
+ instance.RecursiveObject = Realms.Serialization.RealmObjectSerializer.LookupSerializer()!.DeserializeById(context);
+ break;
+ default:
+ context.Reader.SkipValue();
+ break;
+ }
+ }
+
+ protected override void ReadArrayElement(DeepObject3 instance, string name, BsonDeserializationContext context)
+ {
+ // No persisted list/set properties to deserialize
+ }
+
+ protected override void ReadDocumentField(DeepObject3 instance, string name, string fieldName, BsonDeserializationContext context)
+ {
+ // No persisted dictionary properties to deserialize
+ }
+ }
}
}
diff --git a/Tests/Realm.Tests/Generated/Realm.SourceGenerator/Realms.SourceGenerator.RealmGenerator/DeepObject4_generated.cs b/Tests/Realm.Tests/Generated/Realm.SourceGenerator/Realms.SourceGenerator.RealmGenerator/DeepObject4_generated.cs
index 64be4c5bab..949b186836 100644
--- a/Tests/Realm.Tests/Generated/Realm.SourceGenerator/Realms.SourceGenerator.RealmGenerator/DeepObject4_generated.cs
+++ b/Tests/Realm.Tests/Generated/Realm.SourceGenerator/Realms.SourceGenerator.RealmGenerator/DeepObject4_generated.cs
@@ -1,6 +1,7 @@
//
#nullable enable
+using MongoDB.Bson.Serialization;
using NUnit.Framework;
using Realms;
using Realms.Logging;
@@ -26,6 +27,13 @@ namespace Realms.Tests.Database
[Woven(typeof(DeepObject4ObjectHelper)), Realms.Preserve(AllMembers = true)]
public partial class DeepObject4 : IRealmObject, INotifyPropertyChanged, IReflectableType
{
+
+ [Realms.Preserve]
+ static DeepObject4()
+ {
+ Realms.Serialization.RealmObjectSerializer.Register(new DeepObject4Serializer());
+ }
+
///
/// Defines the schema for the class.
///
@@ -266,7 +274,7 @@ internal interface IDeepObject4Accessor : Realms.IRealmAccessor
}
[EditorBrowsable(EditorBrowsableState.Never), Realms.Preserve(AllMembers = true)]
- internal class DeepObject4ManagedAccessor : Realms.ManagedAccessor, IDeepObject4Accessor
+ private class DeepObject4ManagedAccessor : Realms.ManagedAccessor, IDeepObject4Accessor
{
public string? StringValue
{
@@ -282,7 +290,7 @@ public Realms.Tests.Database.DeepObject5? RecursiveObject
}
[EditorBrowsable(EditorBrowsableState.Never), Realms.Preserve(AllMembers = true)]
- internal class DeepObject4UnmanagedAccessor : Realms.UnmanagedAccessor, IDeepObject4Accessor
+ private class DeepObject4UnmanagedAccessor : Realms.UnmanagedAccessor, IDeepObject4Accessor
{
public override ObjectSchema ObjectSchema => DeepObject4.RealmSchema;
@@ -357,5 +365,49 @@ public override IDictionary GetDictionaryValue(string pr
throw new MissingMemberException($"The object does not have a Realm dictionary property with name {propertyName}");
}
}
+
+ [EditorBrowsable(EditorBrowsableState.Never), Realms.Preserve(AllMembers = true)]
+ private class DeepObject4Serializer : Realms.Serialization.RealmObjectSerializerBase
+ {
+ public override string SchemaName => "DeepObject4";
+
+ protected override void SerializeValue(MongoDB.Bson.Serialization.BsonSerializationContext context, BsonSerializationArgs args, DeepObject4 value)
+ {
+ context.Writer.WriteStartDocument();
+
+ WriteValue(context, args, "StringValue", value.StringValue);
+ WriteValue(context, args, "RecursiveObject", value.RecursiveObject);
+
+ context.Writer.WriteEndDocument();
+ }
+
+ protected override DeepObject4 CreateInstance() => new DeepObject4();
+
+ protected override void ReadValue(DeepObject4 instance, string name, BsonDeserializationContext context)
+ {
+ switch (name)
+ {
+ case "StringValue":
+ instance.StringValue = BsonSerializer.LookupSerializer().Deserialize(context);
+ break;
+ case "RecursiveObject":
+ instance.RecursiveObject = Realms.Serialization.RealmObjectSerializer.LookupSerializer()!.DeserializeById(context);
+ break;
+ default:
+ context.Reader.SkipValue();
+ break;
+ }
+ }
+
+ protected override void ReadArrayElement(DeepObject4 instance, string name, BsonDeserializationContext context)
+ {
+ // No persisted list/set properties to deserialize
+ }
+
+ protected override void ReadDocumentField(DeepObject4 instance, string name, string fieldName, BsonDeserializationContext context)
+ {
+ // No persisted dictionary properties to deserialize
+ }
+ }
}
}
diff --git a/Tests/Realm.Tests/Generated/Realm.SourceGenerator/Realms.SourceGenerator.RealmGenerator/DeepObject5_generated.cs b/Tests/Realm.Tests/Generated/Realm.SourceGenerator/Realms.SourceGenerator.RealmGenerator/DeepObject5_generated.cs
index 87ec57eb67..c92b2a4f6a 100644
--- a/Tests/Realm.Tests/Generated/Realm.SourceGenerator/Realms.SourceGenerator.RealmGenerator/DeepObject5_generated.cs
+++ b/Tests/Realm.Tests/Generated/Realm.SourceGenerator/Realms.SourceGenerator.RealmGenerator/DeepObject5_generated.cs
@@ -1,6 +1,7 @@
//
#nullable enable
+using MongoDB.Bson.Serialization;
using NUnit.Framework;
using Realms;
using Realms.Logging;
@@ -26,6 +27,13 @@ namespace Realms.Tests.Database
[Woven(typeof(DeepObject5ObjectHelper)), Realms.Preserve(AllMembers = true)]
public partial class DeepObject5 : IRealmObject, INotifyPropertyChanged, IReflectableType
{
+
+ [Realms.Preserve]
+ static DeepObject5()
+ {
+ Realms.Serialization.RealmObjectSerializer.Register(new DeepObject5Serializer());
+ }
+
///
/// Defines the schema for the class.
///
@@ -258,7 +266,7 @@ internal interface IDeepObject5Accessor : Realms.IRealmAccessor
}
[EditorBrowsable(EditorBrowsableState.Never), Realms.Preserve(AllMembers = true)]
- internal class DeepObject5ManagedAccessor : Realms.ManagedAccessor, IDeepObject5Accessor
+ private class DeepObject5ManagedAccessor : Realms.ManagedAccessor, IDeepObject5Accessor
{
public string? StringValue
{
@@ -268,7 +276,7 @@ public string? StringValue
}
[EditorBrowsable(EditorBrowsableState.Never), Realms.Preserve(AllMembers = true)]
- internal class DeepObject5UnmanagedAccessor : Realms.UnmanagedAccessor, IDeepObject5Accessor
+ private class DeepObject5UnmanagedAccessor : Realms.UnmanagedAccessor, IDeepObject5Accessor
{
public override ObjectSchema ObjectSchema => DeepObject5.RealmSchema;
@@ -328,5 +336,45 @@ public override IDictionary GetDictionaryValue(string pr
throw new MissingMemberException($"The object does not have a Realm dictionary property with name {propertyName}");
}
}
+
+ [EditorBrowsable(EditorBrowsableState.Never), Realms.Preserve(AllMembers = true)]
+ private class DeepObject5Serializer : Realms.Serialization.RealmObjectSerializerBase
+ {
+ public override string SchemaName => "DeepObject5";
+
+ protected override void SerializeValue(MongoDB.Bson.Serialization.BsonSerializationContext context, BsonSerializationArgs args, DeepObject5 value)
+ {
+ context.Writer.WriteStartDocument();
+
+ WriteValue(context, args, "StringValue", value.StringValue);
+
+ context.Writer.WriteEndDocument();
+ }
+
+ protected override DeepObject5 CreateInstance() => new DeepObject5();
+
+ protected override void ReadValue(DeepObject5 instance, string name, BsonDeserializationContext context)
+ {
+ switch (name)
+ {
+ case "StringValue":
+ instance.StringValue = BsonSerializer.LookupSerializer().Deserialize(context);
+ break;
+ default:
+ context.Reader.SkipValue();
+ break;
+ }
+ }
+
+ protected override void ReadArrayElement(DeepObject5 instance, string name, BsonDeserializationContext context)
+ {
+ // No persisted list/set properties to deserialize
+ }
+
+ protected override void ReadDocumentField(DeepObject5 instance, string name, string fieldName, BsonDeserializationContext context)
+ {
+ // No persisted dictionary properties to deserialize
+ }
+ }
}
}
diff --git a/Tests/Realm.Tests/Generated/Realm.SourceGenerator/Realms.SourceGenerator.RealmGenerator/TestNotificationObject_generated.cs b/Tests/Realm.Tests/Generated/Realm.SourceGenerator/Realms.SourceGenerator.RealmGenerator/TestNotificationObject_generated.cs
index 19e1eec1cd..7c6833aa97 100644
--- a/Tests/Realm.Tests/Generated/Realm.SourceGenerator/Realms.SourceGenerator.RealmGenerator/TestNotificationObject_generated.cs
+++ b/Tests/Realm.Tests/Generated/Realm.SourceGenerator/Realms.SourceGenerator.RealmGenerator/TestNotificationObject_generated.cs
@@ -688,6 +688,7 @@ protected override void SerializeValue(MongoDB.Bson.Serialization.BsonSerializat
context.Writer.WriteStartDocument();
WriteValue(context, args, "StringProperty", value.StringProperty);
+ WriteValue(context, args, "IntProperty", value.IntProperty);
WriteList(context, args, "ListSameType", value.ListSameType);
WriteSet(context, args, "SetSameType", value.SetSameType);
WriteDictionary(context, args, "DictionarySameType", value.DictionarySameType);
@@ -695,7 +696,11 @@ protected override void SerializeValue(MongoDB.Bson.Serialization.BsonSerializat
WriteList(context, args, "ListDifferentType", value.ListDifferentType);
WriteSet(context, args, "SetDifferentType", value.SetDifferentType);
WriteDictionary(context, args, "DictionaryDifferentType", value.DictionaryDifferentType);
+ WriteList(context, args, "ListRemappedType", value.ListRemappedType);
+ WriteSet(context, args, "SetRemappedType", value.SetRemappedType);
+ WriteDictionary(context, args, "DictionaryRemappedType", value.DictionaryRemappedType);
WriteValue(context, args, "LinkDifferentType", value.LinkDifferentType);
+ WriteValue(context, args, "LinkAnotherType", value.LinkAnotherType);
context.Writer.WriteEndDocument();
}
@@ -709,20 +714,29 @@ protected override void ReadValue(TestNotificationObject instance, string name,
case "StringProperty":
instance.StringProperty = BsonSerializer.LookupSerializer().Deserialize(context);
break;
+ case "IntProperty":
+ instance.IntProperty = BsonSerializer.LookupSerializer().Deserialize(context);
+ break;
case "LinkSameType":
instance.LinkSameType = Realms.Serialization.RealmObjectSerializer.LookupSerializer()!.DeserializeById(context);
break;
case "LinkDifferentType":
instance.LinkDifferentType = Realms.Serialization.RealmObjectSerializer.LookupSerializer()!.DeserializeById(context);
break;
+ case "LinkAnotherType":
+ instance.LinkAnotherType = Realms.Serialization.RealmObjectSerializer.LookupSerializer()!.DeserializeById(context);
+ break;
case "ListSameType":
case "SetSameType":
case "ListDifferentType":
case "SetDifferentType":
+ case "ListRemappedType":
+ case "SetRemappedType":
ReadArray(instance, name, context);
break;
case "DictionarySameType":
case "DictionaryDifferentType":
+ case "DictionaryRemappedType":
ReadDictionary(instance, name, context);
break;
default:
@@ -747,6 +761,12 @@ protected override void ReadArrayElement(TestNotificationObject instance, string
case "SetDifferentType":
instance.SetDifferentType.Add(Realms.Serialization.RealmObjectSerializer.LookupSerializer()!.DeserializeById(context)!);
break;
+ case "ListRemappedType":
+ instance.ListRemappedType.Add(Realms.Serialization.RealmObjectSerializer.LookupSerializer()!.DeserializeById(context)!);
+ break;
+ case "SetRemappedType":
+ instance.SetRemappedType.Add(Realms.Serialization.RealmObjectSerializer.LookupSerializer()!.DeserializeById(context)!);
+ break;
}
}
@@ -760,6 +780,9 @@ protected override void ReadDocumentField(TestNotificationObject instance, strin
case "DictionaryDifferentType":
instance.DictionaryDifferentType[fieldName] = Realms.Serialization.RealmObjectSerializer.LookupSerializer()!.DeserializeById(context)!;
break;
+ case "DictionaryRemappedType":
+ instance.DictionaryRemappedType[fieldName] = Realms.Serialization.RealmObjectSerializer.LookupSerializer()!.DeserializeById(context)!;
+ break;
}
}
}
From 4052fdc831b12892a9d1549733f8116f010e2c4e Mon Sep 17 00:00:00 2001
From: Ferdinando Papale <4850119+papafe@users.noreply.github.com>
Date: Fri, 9 Feb 2024 13:22:53 +0100
Subject: [PATCH 02/10] Added more tests
---
.../Realm/DatabaseTypes/KeyPathCollection.cs | 12 +++++++++--
.../Realm.Tests/Database/NotificationTests.cs | 20 +++++++++++++++++++
2 files changed, 30 insertions(+), 2 deletions(-)
diff --git a/Realm/Realm/DatabaseTypes/KeyPathCollection.cs b/Realm/Realm/DatabaseTypes/KeyPathCollection.cs
index 9fa8f9a42d..7dc3de04b5 100644
--- a/Realm/Realm/DatabaseTypes/KeyPathCollection.cs
+++ b/Realm/Realm/DatabaseTypes/KeyPathCollection.cs
@@ -22,6 +22,7 @@
using System.Diagnostics;
using System.Linq;
using System.Linq.Expressions;
+using System.Reflection;
namespace Realms;
@@ -171,6 +172,11 @@ private KeyPath(string path)
public static KeyPath For(Expression> expression)
where T : IRealmObject
{
+ if (expression is null)
+ {
+ throw new ArgumentException("The input expression cannot be null");
+ }
+
return new KeyPath(GetFullPath(expression.Body));
}
@@ -178,7 +184,9 @@ public static KeyPath For(Expression> expression)
private static string GetFullPath(Expression expression)
{
- if (expression is MemberExpression memberExpression)
+ if (expression is MemberExpression memberExpression // Either field or property expression
+ && memberExpression.Expression is not null // Filtering out static members
+ && memberExpression.Member is PropertyInfo) // Filtering for property expressions only
{
var subPath = GetFullPath(memberExpression.Expression);
return string.IsNullOrEmpty(subPath) ? memberExpression.Member.Name : $"{subPath}.{memberExpression.Member.Name}";
@@ -189,7 +197,7 @@ private static string GetFullPath(Expression expression)
return string.Empty;
}
- throw new Exception();
+ throw new ArgumentException("The input expression is not a path to a property");
}
///
diff --git a/Tests/Realm.Tests/Database/NotificationTests.cs b/Tests/Realm.Tests/Database/NotificationTests.cs
index 22dda2007d..f9c6da9335 100644
--- a/Tests/Realm.Tests/Database/NotificationTests.cs
+++ b/Tests/Realm.Tests/Database/NotificationTests.cs
@@ -1666,6 +1666,16 @@ public void KeyPath_CanBeBuiltFromExpressions()
Assert.That(keyPath.Path, Is.EqualTo("LinkAnotherType.DictOfDogs"));
}
+ [Test]
+ public void KeyPath_WithInvalidExpressions_ThrowsException()
+ {
+ Assert.That(() => KeyPath.For(t => t.Equals(this)),
+ Throws.Exception.TypeOf().With.Message.EqualTo("The input expression is not a path to a property"));
+
+ Assert.That(() => KeyPath.For(null!),
+ Throws.Exception.TypeOf().With.Message.EqualTo("The input expression cannot be null"));
+ }
+
[Test]
public void KeyPathsCollection_CanBeBuiltInDifferentWays()
{
@@ -1743,6 +1753,16 @@ void AssertKeyPathsCollectionCorrectness(KeyPathsCollection k, IEnumerable KeyPathsCollection.Of(t => t.ListSameType, null!),
+ Throws.Exception.TypeOf().With.Message.EqualTo("The input expression cannot be null"));
+
+ Assert.That(() => KeyPathsCollection.Of(t => t.Equals(this)),
+ Throws.Exception.TypeOf().With.Message.EqualTo("The input expression is not a path to a property"));
+ }
+
[Test]
public void SubscribeWithKeypaths_AnyKeypath_RaisesNotificationsForResults()
{
From 8403227e876d9c6b82fbd52b41cf1458549f34fd Mon Sep 17 00:00:00 2001
From: Ferdinando Papale <4850119+papafe@users.noreply.github.com>
Date: Fri, 9 Feb 2024 13:31:34 +0100
Subject: [PATCH 03/10] Fixed docs
---
Realm/Realm/DatabaseTypes/KeyPathCollection.cs | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/Realm/Realm/DatabaseTypes/KeyPathCollection.cs b/Realm/Realm/DatabaseTypes/KeyPathCollection.cs
index 7dc3de04b5..5b43a455a8 100644
--- a/Realm/Realm/DatabaseTypes/KeyPathCollection.cs
+++ b/Realm/Realm/DatabaseTypes/KeyPathCollection.cs
@@ -159,7 +159,7 @@ private KeyPath(string path)
}
///
- /// Creates a from a lambda expression that specifies a property path for a given realm object type.
+ /// Creates a from an that specifies a property path for a given realm object type.
///
/// The type of the realm object..
/// The expression specifying the path to the property.
From 00605950f2e9b6a3a3d7bf111ae6ee32ef3c5853 Mon Sep 17 00:00:00 2001
From: Ferdinando Papale <4850119+papafe@users.noreply.github.com>
Date: Fri, 9 Feb 2024 13:35:15 +0100
Subject: [PATCH 04/10] Fixed changelog
---
CHANGELOG.md | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/CHANGELOG.md b/CHANGELOG.md
index de0045eeaf..a4fc8900d0 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -7,11 +7,10 @@
* Add support for passing a key paths collection (`KeyPathsCollection`) when using `IRealmCollection.SubscribeForNotifications`. Passing a `KeyPathsCollection` allows to specify which changes in properties should raise a notification.
A `KeyPathsCollection` can be obtained by:
- - building it explicitly by using the method `KeyPathsCollection.Of`;
+ - building it explicitly by using the methods `KeyPathsCollection.Of` or `KeyPathsCollection.Of`;
- building it implicitly with the conversion from a `List` or array of `KeyPath` or strings;
- getting one of the static values `Full` and `Shallow` for full and shallow notifications respectively.
-
For example:
```csharp
var query = realm.All();
@@ -20,6 +19,7 @@
//Equivalent declarations
kpc = KeyPathsCollection.Of("Email", "Name");
+ kpc = KeyPathsCollection.Of(p => p.Email, p => p.Name);
kpc = new List {"Email", "Name"};
query.SubscribeForNotifications(NotificationCallback, kpc);
From 48da0150b63252592e641b0ac2079e8750f104a4 Mon Sep 17 00:00:00 2001
From: Ferdinando Papale <4850119+papafe@users.noreply.github.com>
Date: Mon, 12 Feb 2024 11:11:00 +0100
Subject: [PATCH 05/10] Small fix
---
Realm/Realm/DatabaseTypes/KeyPathCollection.cs | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/Realm/Realm/DatabaseTypes/KeyPathCollection.cs b/Realm/Realm/DatabaseTypes/KeyPathCollection.cs
index 5b43a455a8..6311b70d93 100644
--- a/Realm/Realm/DatabaseTypes/KeyPathCollection.cs
+++ b/Realm/Realm/DatabaseTypes/KeyPathCollection.cs
@@ -184,9 +184,9 @@ public static KeyPath For(Expression> expression)
private static string GetFullPath(Expression expression)
{
- if (expression is MemberExpression memberExpression // Either field or property expression
- && memberExpression.Expression is not null // Filtering out static members
- && memberExpression.Member is PropertyInfo) // Filtering for property expressions only
+ if (expression is MemberExpression memberExpression //// Either field or property expression
+ && memberExpression.Expression is not null //// Filtering out static members
+ && memberExpression.Member is PropertyInfo) //// Filtering for property expressions only
{
var subPath = GetFullPath(memberExpression.Expression);
return string.IsNullOrEmpty(subPath) ? memberExpression.Member.Name : $"{subPath}.{memberExpression.Member.Name}";
From 378d099fdf0834c6f7ba9b0bd34b420c057d214e Mon Sep 17 00:00:00 2001
From: Ferdinando Papale <4850119+papafe@users.noreply.github.com>
Date: Fri, 1 Mar 2024 13:03:12 +0100
Subject: [PATCH 06/10] Apply suggestions from code review
Co-authored-by: Nikola Irinchev
---
Realm/Realm/DatabaseTypes/KeyPathCollection.cs | 8 ++++----
1 file changed, 4 insertions(+), 4 deletions(-)
diff --git a/Realm/Realm/DatabaseTypes/KeyPathCollection.cs b/Realm/Realm/DatabaseTypes/KeyPathCollection.cs
index 6311b70d93..497a70814c 100644
--- a/Realm/Realm/DatabaseTypes/KeyPathCollection.cs
+++ b/Realm/Realm/DatabaseTypes/KeyPathCollection.cs
@@ -87,7 +87,7 @@ public static KeyPathsCollection Of(params KeyPath[] paths)
/// The realm object. type.
/// The array of to use for the .
/// The built from the input array of .
- public static KeyPathsCollection Of(params Expression>[] expressions)
+ public static KeyPathsCollection Of(params Expression>[] expressions)
where T : IRealmObject
{
return Of(expressions.Select(KeyPath.For).ToArray());
@@ -169,15 +169,15 @@ private KeyPath(string path)
/// var keyPath = KeyPath.For<Person>(p => p.Dog.Name);
///
///
- public static KeyPath For(Expression> expression)
+ public static KeyPath For(Expression> expression)
where T : IRealmObject
{
if (expression is null)
{
- throw new ArgumentException("The input expression cannot be null");
+ throw new ArgumentException("The input expression cannot be null", nameof(expression));
}
- return new KeyPath(GetFullPath(expression.Body));
+ return new(GetFullPath(expression.Body));
}
public static implicit operator KeyPath(string s) => new(s);
From 0823a3829508bca47dc39399bced6ce69cc34997 Mon Sep 17 00:00:00 2001
From: Ferdinando Papale <4850119+papafe@users.noreply.github.com>
Date: Fri, 1 Mar 2024 13:27:58 +0100
Subject: [PATCH 07/10] Corrections according to PR
---
.../Realm/DatabaseTypes/KeyPathCollection.cs | 22 ++++++++-----------
.../Realm.Tests/Database/NotificationTests.cs | 8 +++----
2 files changed, 12 insertions(+), 18 deletions(-)
diff --git a/Realm/Realm/DatabaseTypes/KeyPathCollection.cs b/Realm/Realm/DatabaseTypes/KeyPathCollection.cs
index 6311b70d93..7575af57ff 100644
--- a/Realm/Realm/DatabaseTypes/KeyPathCollection.cs
+++ b/Realm/Realm/DatabaseTypes/KeyPathCollection.cs
@@ -184,20 +184,16 @@ public static KeyPath For(Expression> expression)
private static string GetFullPath(Expression expression)
{
- if (expression is MemberExpression memberExpression //// Either field or property expression
- && memberExpression.Expression is not null //// Filtering out static members
- && memberExpression.Member is PropertyInfo) //// Filtering for property expressions only
+ return expression switch
{
- var subPath = GetFullPath(memberExpression.Expression);
- return string.IsNullOrEmpty(subPath) ? memberExpression.Member.Name : $"{subPath}.{memberExpression.Member.Name}";
- }
- else if (expression is ParameterExpression)
- {
- // This is the parameter of the expression, nothing to add
- return string.Empty;
- }
-
- throw new ArgumentException("The input expression is not a path to a property");
+ // MemberExpression: field or property expression;
+ // Expression == null for static members;
+ // Member: PropertyInfo to filter out field access
+ MemberExpression { Expression: { } innerExpression, Member: PropertyInfo pi } =>
+ innerExpression is ParameterExpression ? pi.Name : $"{GetFullPath(innerExpression)}.{pi.Name}",
+ ParameterExpression => string.Empty,
+ _ => throw new ArgumentException("The input expression is not a path to a property"),
+ };
}
///
diff --git a/Tests/Realm.Tests/Database/NotificationTests.cs b/Tests/Realm.Tests/Database/NotificationTests.cs
index f9c6da9335..770d79a8f9 100644
--- a/Tests/Realm.Tests/Database/NotificationTests.cs
+++ b/Tests/Realm.Tests/Database/NotificationTests.cs
@@ -1735,21 +1735,19 @@ void AssertKeyPathsCollectionCorrectness(KeyPathsCollection k, IEnumerable { "ListSameType", "LinkAnotherType.DictOfDogs" };
- kpc = KeyPathsCollection.Of(t => t.ListSameType, t => t.LinkAnotherType!.DictOfDogs);
+ var kpc = KeyPathsCollection.Of(t => t.ListSameType, t => t.LinkAnotherType!.DictOfDogs);
AssertKeyPathsCollectionCorrectness(kpc, expected);
kpc = KeyPathsCollection.Of(KeyPath.For(t => t.ListSameType),
KeyPath.For(t => t.LinkAnotherType!.DictOfDogs));
AssertKeyPathsCollectionCorrectness(kpc, expected);
- void AssertKeyPathsCollectionCorrectness(KeyPathsCollection k, IEnumerable expected)
+ void AssertKeyPathsCollectionCorrectness(KeyPathsCollection k, IEnumerable expectedStrings)
{
Assert.That(k.Type, Is.EqualTo(KeyPathsCollectionType.Explicit));
- Assert.That(k.GetStrings(), Is.EqualTo(expected));
+ Assert.That(k.GetStrings(), Is.EqualTo(expectedStrings));
}
}
From 5f99655cd79c186cd7979071341764ac8c79ebd5 Mon Sep 17 00:00:00 2001
From: Ferdinando Papale <4850119+papafe@users.noreply.github.com>
Date: Fri, 1 Mar 2024 13:38:12 +0100
Subject: [PATCH 08/10] Fixed tests and merged main
---
Tests/Realm.Tests/Database/NotificationTests.cs | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/Tests/Realm.Tests/Database/NotificationTests.cs b/Tests/Realm.Tests/Database/NotificationTests.cs
index 770d79a8f9..bb7508e4fe 100644
--- a/Tests/Realm.Tests/Database/NotificationTests.cs
+++ b/Tests/Realm.Tests/Database/NotificationTests.cs
@@ -1673,7 +1673,7 @@ public void KeyPath_WithInvalidExpressions_ThrowsException()
Throws.Exception.TypeOf().With.Message.EqualTo("The input expression is not a path to a property"));
Assert.That(() => KeyPath.For(null!),
- Throws.Exception.TypeOf().With.Message.EqualTo("The input expression cannot be null"));
+ Throws.Exception.TypeOf().With.Message.EqualTo("The input expression cannot be null (Parameter 'expression')"));
}
[Test]
@@ -1755,7 +1755,7 @@ void AssertKeyPathsCollectionCorrectness(KeyPathsCollection k, IEnumerable KeyPathsCollection.Of(t => t.ListSameType, null!),
- Throws.Exception.TypeOf().With.Message.EqualTo("The input expression cannot be null"));
+ Throws.Exception.TypeOf().With.Message.EqualTo("The input expression cannot be null (Parameter 'expression')"));
Assert.That(() => KeyPathsCollection.Of(t => t.Equals(this)),
Throws.Exception.TypeOf().With.Message.EqualTo("The input expression is not a path to a property"));
From afd96bb634cd17634dc5e7cd31520e3e8b7920d0 Mon Sep 17 00:00:00 2001
From: Ferdinando Papale <4850119+papafe@users.noreply.github.com>
Date: Tue, 5 Mar 2024 14:11:00 +0100
Subject: [PATCH 09/10] Corrections
---
CHANGELOG.md | 6 ++++++
Realm/Realm/DatabaseTypes/KeyPathCollection.cs | 8 +++-----
Tests/Realm.Tests/Database/NotificationTests.cs | 12 ++++++------
3 files changed, 15 insertions(+), 11 deletions(-)
diff --git a/CHANGELOG.md b/CHANGELOG.md
index a4fc8900d0..f48e27378a 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -11,16 +11,22 @@
- building it implicitly with the conversion from a `List` or array of `KeyPath` or strings;
- getting one of the static values `Full` and `Shallow` for full and shallow notifications respectively.
+ A `KeyPath` can be obtained by implicit conversion from a string or built from an expression using the `KeyPath.ForExpression` method.
+
For example:
```csharp
var query = realm.All();
+ KeyPath kp1 = "Email";
+ KeyPath kp2 = KeyPath.ForExpression(p => p.Name);
+
KeyPathsCollection kpc;
//Equivalent declarations
kpc = KeyPathsCollection.Of("Email", "Name");
kpc = KeyPathsCollection.Of(p => p.Email, p => p.Name);
kpc = new List {"Email", "Name"};
+ kpc = new List {kp1, kp2};
query.SubscribeForNotifications(NotificationCallback, kpc);
```
diff --git a/Realm/Realm/DatabaseTypes/KeyPathCollection.cs b/Realm/Realm/DatabaseTypes/KeyPathCollection.cs
index ab89f3b68c..57e63ffe80 100644
--- a/Realm/Realm/DatabaseTypes/KeyPathCollection.cs
+++ b/Realm/Realm/DatabaseTypes/KeyPathCollection.cs
@@ -90,7 +90,7 @@ public static KeyPathsCollection Of(params KeyPath[] paths)
public static KeyPathsCollection Of(params Expression>[] expressions)
where T : IRealmObject
{
- return Of(expressions.Select(KeyPath.For).ToArray());
+ return Of(expressions.Select(KeyPath.ForExpression).ToArray());
}
///
@@ -140,13 +140,11 @@ IEnumerator IEnumerable.GetEnumerator()
}
}
-//TODO Fix changelog
-
///
/// Represents a key path that can be used as a part of a when subscribing for notifications.
/// A can be implicitly built from a string, where the string is the name of a property (e.g "FirstName"), eventually dotted to indicated nested properties.
/// (e.g "Dog.Name"). Wildcards can also be used in key paths to capture all properties at a given level (e.g "*", "Friends.*" or "*.FirstName").
-/// A can also be built using the method, that creates the corresponding
+/// A can also be built using the method, that creates the corresponding
/// to the property path represented by the input expression.
///
public readonly struct KeyPath
@@ -169,7 +167,7 @@ private KeyPath(string path)
/// var keyPath = KeyPath.For<Person>(p => p.Dog.Name);
///
///
- public static KeyPath For(Expression> expression)
+ public static KeyPath ForExpression(Expression> expression)
where T : IRealmObject
{
if (expression is null)
diff --git a/Tests/Realm.Tests/Database/NotificationTests.cs b/Tests/Realm.Tests/Database/NotificationTests.cs
index bb7508e4fe..8f52d4cb67 100644
--- a/Tests/Realm.Tests/Database/NotificationTests.cs
+++ b/Tests/Realm.Tests/Database/NotificationTests.cs
@@ -1659,20 +1659,20 @@ public void KeyPath_CanBeBuiltFromExpressions()
{
KeyPath keyPath;
- keyPath = KeyPath.For(t => t.ListSameType);
+ keyPath = KeyPath.ForExpression(t => t.ListSameType);
Assert.That(keyPath.Path, Is.EqualTo("ListSameType"));
- keyPath = KeyPath.For(t => t.LinkAnotherType!.DictOfDogs);
+ keyPath = KeyPath.ForExpression(t => t.LinkAnotherType!.DictOfDogs);
Assert.That(keyPath.Path, Is.EqualTo("LinkAnotherType.DictOfDogs"));
}
[Test]
public void KeyPath_WithInvalidExpressions_ThrowsException()
{
- Assert.That(() => KeyPath.For(t => t.Equals(this)),
+ Assert.That(() => KeyPath.ForExpression(t => t.Equals(this)),
Throws.Exception.TypeOf().With.Message.EqualTo("The input expression is not a path to a property"));
- Assert.That(() => KeyPath.For(null!),
+ Assert.That(() => KeyPath.ForExpression(null!),
Throws.Exception.TypeOf().With.Message.EqualTo("The input expression cannot be null (Parameter 'expression')"));
}
@@ -1740,8 +1740,8 @@ public void KeyPathsCollection_CanBeBuiltFromExpressions()
var kpc = KeyPathsCollection.Of(t => t.ListSameType, t => t.LinkAnotherType!.DictOfDogs);
AssertKeyPathsCollectionCorrectness(kpc, expected);
- kpc = KeyPathsCollection.Of(KeyPath.For(t => t.ListSameType),
- KeyPath.For(t => t.LinkAnotherType!.DictOfDogs));
+ kpc = KeyPathsCollection.Of(KeyPath.ForExpression(t => t.ListSameType),
+ KeyPath.ForExpression(t => t.LinkAnotherType!.DictOfDogs));
AssertKeyPathsCollectionCorrectness(kpc, expected);
void AssertKeyPathsCollectionCorrectness(KeyPathsCollection k, IEnumerable expectedStrings)
From 8541a85e43541bfd80fd9df632fd3e6384a827fc Mon Sep 17 00:00:00 2001
From: Ferdinando Papale <4850119+papafe@users.noreply.github.com>
Date: Tue, 5 Mar 2024 18:21:34 +0100
Subject: [PATCH 10/10] Corrected tests
---
Tests/Realm.Tests/Database/NotificationTests.cs | 8 ++++----
1 file changed, 4 insertions(+), 4 deletions(-)
diff --git a/Tests/Realm.Tests/Database/NotificationTests.cs b/Tests/Realm.Tests/Database/NotificationTests.cs
index f8e72fa145..96e99f754e 100644
--- a/Tests/Realm.Tests/Database/NotificationTests.cs
+++ b/Tests/Realm.Tests/Database/NotificationTests.cs
@@ -1670,10 +1670,10 @@ public void KeyPath_CanBeBuiltFromExpressions()
public void KeyPath_WithInvalidExpressions_ThrowsException()
{
Assert.That(() => KeyPath.ForExpression(t => t.Equals(this)),
- Throws.Exception.TypeOf().With.Message.EqualTo("The input expression is not a path to a property"));
+ Throws.Exception.TypeOf().With.Message.Contains("The input expression is not a path to a property"));
Assert.That(() => KeyPath.ForExpression(null!),
- Throws.Exception.TypeOf().With.Message.EqualTo("The input expression cannot be null (Parameter 'expression')"));
+ Throws.Exception.TypeOf().With.Message.Contains("The input expression cannot be null"));
}
[Test]
@@ -1755,10 +1755,10 @@ void AssertKeyPathsCollectionCorrectness(KeyPathsCollection k, IEnumerable KeyPathsCollection.Of(t => t.ListSameType, null!),
- Throws.Exception.TypeOf().With.Message.EqualTo("The input expression cannot be null (Parameter 'expression')"));
+ Throws.Exception.TypeOf().With.Message.Contains("The input expression cannot be null"));
Assert.That(() => KeyPathsCollection.Of(t => t.Equals(this)),
- Throws.Exception.TypeOf().With.Message.EqualTo("The input expression is not a path to a property"));
+ Throws.Exception.TypeOf().With.Message.Contains("The input expression is not a path to a property"));
}
[Test]