2016-06-23 3 views
10

Есть ли способ, когда я читаю объект из Realm, что он может стать автономным или неуправляемым объектом? В EF это называется отслеживанием. Использование для этого было бы, когда я хочу реализовать больше бизнес-логики для своих объектов данных до того, как они будут обновлены в постоянном хранилище данных. Я могу дать RealmObject для ViewModel, но когда изменения возвращаются из ViewModel, я хочу сравнить отключенный объект с объектом в хранилище данных, чтобы определить, что было изменено, поэтому, если бы был способ, которым я мог отключиться объект из Realm, когда я даю его ViewModel, тогда я могу лучше управлять тем, какие свойства изменились, используя мою логику логики, чтобы сделать то, что мне нужно, а затем сохранить изменения обратно в область.Как получить автономный/неуправляемый объект RealmObject с использованием Realm Xamarin

Я понимаю, что в Realm много магии, и многие люди не захотят добавлять такой слой, но в моем приложении я не могу иметь пользовательский интерфейс, непосредственно обновляющий хранилище данных, если только не возникает событие, может также подписаться, а затем присоединить мою бизнес-логику таким образом.

Я только видел одно событие и, похоже, не выполняет это действие.

Благодарим за помощь.

ответ

1

В настоящее время в интерфейсе Xamarin отсутствует возможность добавить его. Интерфейс Java уже имеет copyFromRealm, который выполняет глубокую копию. Это также имеет парное слияние copyToRealmOrUpdate.

См. Realm github issue для дальнейшего обсуждения.

Однако, как проблема дизайна, это действительно соответствует вашим потребностям оптимальным образом?

Я использовал конверторы в приложениях WPF для вставки логики в привязку - это available in Xamarin Forms.

Другим способом в формах Xamarin является использование Поведений, введенных в blog article и покрытых in the API.

Эти подходы больше связаны с добавлением логики между пользовательским интерфейсом и ViewModel, которые вы можете рассматривать как часть ViewModel, но до того, как обновления будут распространены на связанные значения.

+0

В моем приложении, мне нужно знать все свойства каждого объекта, который обновляется с помощью пользовательского интерфейса так что я могу записать его в таблицу по причинам синхронизации. Поэтому мне действительно нужен DataLayer с логикой для этого. Если бы я создавал приложение, в котором использовались только локальные данные, я бы подумал, что иметь все объекты «живые» или «управляемые» будут иметь смысл. – J3RM

2

До добавления в Царство для Xamarin я добавил свойство моей модели, которое создает копию объекта. Кажется, это работает для моего использования. Сообщения об ошибках TwoWay Binding также не являются проблемой. Для более сложного приложения я не хочу размещать бизнес или логику данных в ViewModel. Это позволяет всем магам форм xamarin работать, а я - реализовать логику, когда наконец придет время сохранить изменения обратно в царство.

[Ignored] 
    public Contact ToStandalone() 
    { 
     return new Contact() 
     { 
      companyName = this.companyName, 
      dateAdded = this.dateAdded, 
      fullName = this.fullName, 
      gender = this.gender, 
      website = this.website 
     }; 
    } 

Однако, если есть какие-либо отношения, этот метод не работает для отношений. Копирование списка на самом деле не является вариантом, так как отношения can not существуют, если объект не привязан к Realm, я прочитал это где-то, но не могу найти его сейчас. Поэтому я предполагаю, что мы будем ждать дополнений к структуре.

2

Во-первых, получить json NUGET:

PM> Install-Package Newtonsoft.Json

И, попробуйте это "взломать":

Deserialize модифицированный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' имеет только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; 
} 

.

вы получите пустой RealmObject тело после того, как Realm теперь реализованы же стратегию LazyLoad

Запись вниз живойRealmObjectи (деактивировать) экземпляр области действия в объекте с помощьюReflection. И установите записанные значения наRealmObject. С обработаны всеILists внутри тоже.

 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

+0

Это выглядит многообещающе! Вам нужно скомпилировать собственную копию класса RealmObject или добавить это как расширение? –

+0

У меня есть метод 'JsonConvert', который работает с заметной задержкой. Когда я пытаюсь использовать полный метод, я получаю 'System.ArgumentException: метод набора свойств не найден. ' –

+0

My bad - он пытался обработать свойство, которое было только для чтения. :) Получил, что все в квадрате. Спасибо за обходной путь! –

Смежные вопросы