如何使用Realm Xamarin获得独立/不受管理的RealmObject [英] How to get a standalone / unmanaged RealmObject using Realm Xamarin
问题描述
当我从Realm读取对象时,有没有一种方法可以使其成为独立对象或不受管理的对象?在EF中,这称为无跟踪.当我要在持久性数据存储上更新数据对象之前在我的数据对象上实现更多业务逻辑时,将使用此方法.我可能想将RealmObject提供给ViewModel,但是当更改从ViewModel返回时,我想将断开连接的对象与数据存储区中的对象进行比较,以确定已更改的内容,因此,如果有一种方法可以断开连接将对象提供给ViewModel时,可以使用Realm的业务逻辑来更好地管理已更改的属性,使用我的业务逻辑执行所需的操作,然后将更改保存回Realm.
Is there a way that when I read an object from Realm that it can become a standalone or unmanaged object? In EF, this is called no tracking. The usage for this would be when I want to implement more business logic on my data objects before they are updated on the persistent data storage. I may want to give the RealmObject to a ViewModel, but when the changes come back from the ViewModel, I want to compare the disconnected object to the object in the datastore to determine what was changed, so If there was a way that I could disconnect the object from Realm when I give it to the ViewModel, then I can better manage what properties have changed, using my biz logic to do what I need, then save the changes back to realm.
我了解Realm确实具有很多魔力,很多人都不想添加这样的图层,但是在我的应用程序中,除非出现引发的事件,否则我无法真正让UI直接更新数据存储区也订阅,然后以这种方式附加我的业务逻辑.
I understand Realm does a lot of magic and many people will not want to add a layer like this but in my app, I cant really have the UI directly updating the datastore, unless there is a event that is raised that I can subscribe too and then attach my business logic this way.
我只看到一个事件,并且似乎没有执行此操作.
I only saw one event and it does not appear to perform this action.
感谢您的帮助.
推荐答案
首先,获取 json NUGET :
PM>安装软件包Newtonsoft.Json
然后,尝试此"hack" :
反序列化修改后的 IsManaged
属性可以解决问题.
public d DetachObject<d>(d Model) where d : RealmObject
{
return Newtonsoft.Json.JsonConvert.DeserializeObject<d>(
Newtonsoft.Json.JsonConvert.SerializeObject(Model)
.Replace(",\"IsManaged\":true", ",\"IsManaged\":false")
);
}
.
如果您在JsonConvert上遇到速度慢的问题:
根据源代码
,"IsManaged"属性仅具有 get
访问器和 return true
(在私有字段中) _realm
可用
According to source code
, the 'IsManaged' property only has get
accessor and return true
when private field _realm
which is available
因此,我们必须将字段实例设置为 _realm
为 null
public d DetachObject<d>(d Model) where d : RealmObject
{
typeof(RealmObject).GetField("_realm",
System.Reflection.BindingFlags.Instance | System.Reflection.BindingFlags.NonPublic)
.SetValue(Model, null);
return Model.IsManaged ? null : Model;
}
.
在Realm实施与 LazyLoad
记录实时 RealmObject
,并通过 Reflection
取消激活对象中的领域实例.然后将记录的值设置回 RealmObject
. 也处理了里面的所有 IList
.
Record down live RealmObject
and (deactivate) realm instance in object by Reflection
. And set back recorded values to RealmObject
. With handled all the IList
s inside too.
public d DetachObject<d>(d Model) where d : RealmObject
{
return (d)DetachObjectInternal(Model);
}
private object DetachObjectInternal(object Model)
{
//Record down properties and fields on RealmObject
var Properties = Model.GetType().GetProperties(System.Reflection.BindingFlags.Instance | System.Reflection.BindingFlags.Public)
.Where(x => x.Name != "ObjectSchema" && x.Name != "Realm" && x.Name != "IsValid" && x.Name != "IsManaged" && x.Name != "IsDefault")
.Select(x =>(x.PropertyType.Name == "IList`1")? ("-" + x.Name, x.GetValue(Model)) : (x.Name, x.GetValue(Model))).ToList();
var Fields = Model.GetType().GetFields(System.Reflection.BindingFlags.Instance | System.Reflection.BindingFlags.Public)
.Select(x => (x.Name, x.GetValue(Model))).ToList();
//Unbind realm instance from object
typeof(RealmObject).GetField("_realm", System.Reflection.BindingFlags.Instance | System.Reflection.BindingFlags.NonPublic).SetValue(Model, null);
//Set back the properties and fields into RealmObject
foreach (var field in Fields)
{
Model.GetType().GetField(field.Item1, System.Reflection.BindingFlags.Instance | System.Reflection.BindingFlags.Public).SetValue(Model, field.Item2);
}
foreach (var property in Properties.OrderByDescending(x=>x.Item1[0]).ToList())
{
if (property.Item1[0] == '-')
{
int count = (int)property.Item2.GetType().GetMethod("get_Count").Invoke(property.Item2, null);
if (count > 0)
{
if (property.Item2.GetType().GenericTypeArguments[0].BaseType.Name == "RealmObject")
{
for (int i = 0; i < count; i++)
{
var seter = property.Item2.GetType().GetMethod("set_Item");
var geter = property.Item2.GetType().GetMethod("get_Item");
property.Item2.GetType().GetField("_realm", System.Reflection.BindingFlags.Instance | System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Public).SetValue(property.Item2, null);
DetachObjectInternal(geter.Invoke(property.Item2, new object[] { i }));
}
}
}
}
else
{
Model.GetType().GetProperty(property.Item1, System.Reflection.BindingFlags.Instance | System.Reflection.BindingFlags.Public).SetValue(Model, property.Item2);
}
}
return Model;
}
.
对于RealmObject
的列表,请使用Select():
For List of the RealmObject
, Using Select():
DBs.All<MyRealmObject>().ToList().Select(t => DBs.DetachObject(t)).ToList();
.
(Java)如果您使用Java,则不需要此:
也许有一天,.NET Realm会提供此功能
Realm.copyFromRealm();
#xamarin#C##Realm #RealmObject #detach #managed #IsManaged #copyFromRealm
这篇关于如何使用Realm Xamarin获得独立/不受管理的RealmObject的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!