当我从Realm读取对象时,有没有一种方法可以使其成为独立对象或不受管理的对象?在EF中,这称为无跟踪。当我要在持久性数据存储上更新数据对象之前在我的数据对象上实现更多业务逻辑时,将使用此方法。我可能想将RealmObject提供给ViewModel,但是当更改从ViewModel返回时,我想将断开连接的对象与数据存储区中的对象进行比较,以确定已更改的内容,因此,如果有一种方法可以断开连接将对象提供给ViewModel时,可以使用Realm的业务逻辑来更好地管理已更改的属性,使用我的业务逻辑执行所需的操作,然后将更改保存回Realm。
我了解Realm确实具有很多魔力,很多人都不想添加这样的图层,但是在我的应用程序中,除非出现引发我也可以订阅的事件,否则我无法真正让UI直接更新数据存储区。然后以这种方式附加我的业务逻辑。
我只看到一个事件,但似乎没有执行此操作。
感谢你的协助。
最佳答案
首先,获取json NUGET:
并且,尝试以下“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的速度变慢:
根据source code
,“IsManaged”属性仅在私有(private)字段
get
可用时才具有return true
访问器和_realm
。因此,我们必须将字段
_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
正文记录实时
RealmObject
并通过Reflection
停用对象中的 Realm 实例。并将记录的值设置回RealmObject
。也处理了里面的所有IList
。 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():DBs.All<MyRealmObject>().ToList().Select(t => DBs.DetachObject(t)).ToList();
。
(Java)如果您使用的是Java ,则不需要:
也许有一天,此功能将出现在.NET Realm中
Realm.copyFromRealm();
#xamarin#C##Realm #RealmObject #detach #managed #IsManaged #copyFromRealm
关于xamarin - 如何使用Realm Xamarin获得独立/不受管理的RealmObject,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/37999630/