2016-06-23 39 views
10

C'è un modo in cui quando leggo un oggetto da Reame può diventare un oggetto autonomo o non gestito? In EF, questo è chiamato no tracking. L'utilizzo per questo sarebbe quando voglio implementare più logica di business sui miei oggetti di dati prima che vengano aggiornati sull'archiviazione dei dati persistenti. Potrei voler dare RealmObject a un ViewModel, ma quando le modifiche tornano dal ViewModel, voglio confrontare l'oggetto disconnesso con l'oggetto nel datastore per determinare cosa è stato cambiato, quindi Se c'era un modo che potevo disconnettere l'oggetto di Realm quando lo conferisco al ViewModel, quindi posso gestire meglio quali proprietà sono state modificate, usando la mia logica di biz per fare ciò di cui ho bisogno, quindi salvare le modifiche sul reame.Come ottenere un RealmObject standalone/non gestito utilizzando Realm Xamarin

Capisco che il Realm fa molta magia e molte persone non vorranno aggiungere un livello come questo ma nella mia app, non posso davvero avere l'interfaccia utente che aggiorna direttamente il datastore, a meno che non ci sia un evento che viene sollevato puoi anche iscriverti e quindi collegare la mia logica aziendale in questo modo.

Ho visto solo un evento e non sembra eseguire questa azione.

Grazie per l'assistenza.

risposta

1

Attualmente non nell'interfaccia Xamarin ma potremmo aggiungerlo. L'interfaccia Java ha già copyFromRealm che esegue una copia profonda. Questo ha anche una fusione accoppiata copyToRealmOrUpdate.

Vedere Realm github issue per ulteriori discussioni.

Tuttavia, come un problema di progettazione, è davvero questo soddisfare le vostre esigenze in modo ottimale?

Ho utilizzato i convertitori nelle app WPF per inserire la logica nell'associazione - questi sono available in Xamarin Forms.

Un altro modo nei moduli Xamarin è l'utilizzo di Behaviors, come introdotto nello e coperto in the API.

Questi approcci riguardano più l'aggiunta di logica tra l'interfaccia utente e ViewModel, che è possibile considerare come parte di ViewModel, ma prima che gli aggiornamenti vengano propagati ai valori associati.

+0

Nella mia app, ho bisogno di sapere ogni proprietà di ogni oggetto che viene aggiornato dal UI in modo che io possa registrarlo su una tabella per motivi di sincronizzazione. Quindi ho davvero bisogno di un DataLayer con logica per questo. Se stavo creando un'app che utilizzava solo dati locali, avrei pensato che avere tutti gli oggetti "live" o "gestiti" avrebbe senso. – J3RM

2

Fino a quando non è stato aggiunto a Realm per Xamarin, ho aggiunto una proprietà al mio modello che crea una copia dell'oggetto. Questo sembra funzionare per il mio uso. I messaggi di errore di TwoWay Binding ora non rappresentano un problema. Per un'applicazione più complicata, non voglio inserire business o dati logic in ViewModel. Questo permette a tutte le forme di Magic di xamarin di funzionare e io di implementare la logica quando è finalmente il momento di salvare le modifiche sul reame.

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

Tuttavia, se esistono relazioni, questo metodo non funziona per le relazioni. Copiare l'elenco non è davvero un'opzione in quanto la relazione non può esistere se l'oggetto non è collegato al reame, ho letto questo in cui, non riesco a trovarlo per ref ora. Quindi immagino che aspetteremo le aggiunte al framework.

2

primo luogo, ottenere json NUGET:

PM> Install-Package Newtonsoft.JSON

E, provate questo "hack":

deserializzare il modificato proprietàIsManagedfa i trucchi.

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") 
      ); 
} 

.

Se di fronte rallentamento on JsonConvert:

Secondo source code , di proprietà della 'ismanaged' ha sologetdi accesso ereturn truequando privata campo_realmche è disponibile

Quindi, dobbiamo impostare il esempio di campo_realm-nullfa i trucchi

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; 
} 

.

Otterrete vuoto RealmObject corpo dopo Realm sono ora implementata stessa strategia LazyLoad

record verso il basso dal vivo esempio regnoRealmObjecte (disattivare) in oggettoReflection. E ripristinare i valori registrati suRealmObject. Con anche tutti gliILists interni.

 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; 
     } 

.

per la lista del RealmObject, Usare Select():

DBs.All<MyRealmObject>().ToList().Select(t => DBs.DetachObject(t)).ToList(); 

.

(Java) non avete bisogno di questo se sei in java:

Forse un giorno, questa funzionalità verrà a.NET Realm

Realm.copyFromRealm(); 

#xamarin # C# #Realm #RealmObject #detach #managed #IsManaged #copyFromRealm

+0

Questo sembra promettente! Devi compilare la tua copia della classe RealmObject o puoi aggiungerla come estensione? –

+0

Ho il metodo 'JsonConvert' che funziona, con il ritardo evidente. Quando provo a usare il metodo completo, ottengo un 'System.ArgumentException: metodo set di proprietà non trovato. –

+0

Il mio male: si stava tentando di gestire una proprietà che era in sola lettura. :) Ho capito tutto. Grazie per la soluzione! –