Last active
September 21, 2023 12:50
-
-
Save vineetchoudhary/94407b9c2bc217c36e3c244ed1af3e4f to your computer and use it in GitHub Desktop.
Get a standalone / unmanaged / Clone RealmObject using Realm Xamarin
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using System; | |
using System.Collections; | |
using System.Collections.Generic; | |
using System.Reflection; | |
using Realms; | |
namespace ProjectName.Core.Extensions | |
{ | |
public static class RealmExtension | |
{ | |
public static T Clone<T>(this T source) where T: new() | |
{ | |
//If source is null return null | |
if (source == null) | |
return default(T); | |
var target = new T(); | |
var targetType = typeof(T); | |
//List of skip namespaces | |
var skipNamespaces = new List<string> | |
{ | |
typeof(Realm).Namespace | |
}; | |
//Get the Namespace name of Generic Collection | |
var collectionNamespace = typeof(List<string>).Namespace; | |
//flags to get properties | |
var flags = BindingFlags.IgnoreCase | BindingFlags.DeclaredOnly | BindingFlags.Public | BindingFlags.Instance; | |
//Get target properties list which follows the flags | |
var targetProperties = targetType.GetProperties(flags); | |
//if traget properties is null then return default target | |
if (targetProperties == null) | |
return target; | |
//enumerate properties | |
foreach (var property in targetProperties) | |
{ | |
//skip property if it's belongs to namespace available in skipNamespaces list | |
if (skipNamespaces.Contains(property.DeclaringType.Namespace)) | |
continue; | |
//Get property information and check if we can write value in it | |
var propertyInfo = targetType.GetProperty(property.Name, flags); | |
if (propertyInfo == null || !property.CanWrite) | |
continue; | |
//Get value from the source | |
var sourceValue = property.GetValue(source); | |
//If property derived from the RealmObject then Clone that too | |
if (property.PropertyType.IsSubclassOf(typeof(RealmObject)) && (sourceValue is RealmObject)) | |
{ | |
var propertyType = property.PropertyType; | |
var convertedSourceValue = Convert.ChangeType(sourceValue, propertyType); | |
sourceValue = typeof(RealmExtension).GetMethod("Clone", BindingFlags.Static | BindingFlags.Public) | |
.MakeGenericMethod(propertyType).Invoke(convertedSourceValue, new[] { convertedSourceValue }); | |
} | |
//Check if property belongs to the collection namespace and original value is not null | |
if (property.PropertyType.Namespace == collectionNamespace && sourceValue != null) | |
{ | |
//get the type of the property (currently only supported List) | |
var listType = property.PropertyType; | |
//Create new instance of listType | |
var newList = (IList)Activator.CreateInstance(listType); | |
//Convert source value into the list type | |
var convertedSourceValue = Convert.ChangeType(sourceValue, listType) as IEnumerable; | |
//Enumerate source list and recursively call Clone method on each object | |
foreach (var item in convertedSourceValue) | |
{ | |
var value = typeof(RealmExtension).GetMethod("Clone", BindingFlags.Static | BindingFlags.Public) | |
.MakeGenericMethod(item.GetType()).Invoke(item, new[] { item }); | |
newList.Add(value); | |
} | |
//update source value | |
sourceValue = newList; | |
} | |
//set updated original value into the target | |
propertyInfo.SetValue(target, sourceValue); | |
} | |
return target; | |
} | |
} | |
} |
Currently doesn't support the list object on the root. You can enumerate your list and clone object one by one and put the back into the list.
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Wery fast, but I need to Clone object with related data in IList. How can I do that?