2013-08-16 171 views
1

我試圖在OnPostUpdate事件中獲取更新實體的舊狀態。 @event參數的OldState屬性將對象作爲數組返回,我需要它作爲對象。我試過如下:NHibernate事件偵聽深克隆對象

public class EventListener : IPostUpdateEventListener { 
    public void OnPostUpdate(PostUpdateEvent @event) { 
     // Get the property names to align with the indexes of the old state 
     var propertyNames = @event.Persister.PropertyNames; 

     // Get the original entity values 
     var type = @event.Entity.GetType(); 
     var original = Activator.CreateInstance(type); 

     // Set the values 
    for (var i = 0; i < @event.OldState.Length; i++) { 
     // Get the property and value 
     var property = type.GetProperty(@event.Persister.PropertyNames[i]); 
     var value = @event.OldState[i]; 

     if (property.CanWrite && !(@event.Persister.PropertyTypes[i] is CollectionType)) { 
      if (value != null && (@event.Persister.PropertyTypes[i] is ComponentType || @event.Persister.PropertyTypes[i] is EntityType)) 
       property.SetValue(original, CloneObject(value)); 
      else 
       property.SetValue(original, value); 
     } 
    } 
} 

這裏的CLONEOBJECT方法:

private object CloneObject(object source) { 
    var sourceType = source.GetType(); 
    var target = Activator.CreateInstance(sourceType, true); 

    foreach (var property in type.GetProperties()) { 
     var value = property.GetValue(source, null); 

     if (property.CanWrite && (property.PropertyType == typeof(string) || !typeof(IEnumerable).IsAssignableFrom(property.PropertyType)) && !property.PropertyType.IsInterface) { 
      if (value != null && typeof(IEntity).IsAssignableFrom(property.PropertyType)) 
       property.SetValue(target, CloneObject(value)); 
      else 
       property.SetValue(target, value); 
     } 
    } 

    return target; 
} 

我做的第一件事是環比在原來的對象的屬性,然後我試圖處理組件和引用類型(忽略列表)。這會正確複製對象。然而,隨後引發錯誤:

collection [Models.ContentType.Tags] was not processed by flush()

編輯:將contentType類是我更新的屬性的一個類型。這是它的實施,因爲它幫助:

public class ContentType : Entity<int> { 
    public virtual string Name { get; set; } 

    public virtual IList<ContentTag> Tags { get; set; } 

    public ContentType() { 
     Tags = new List<ContentTag>(); 
    } 
} 

我也遇到類似的錯誤,當我試圖讓其他實體的舊狀態。如果有人能告訴我正確的方式來做到這一點,我會很感激。由於

+0

您遇到了什麼問題? –

+0

每當它更新實體時,我都會收到錯誤「集合[Models.User.Addresses]未由flush()處理」。 – nfplee

回答

1

編輯

雖然你似乎並不被觸及任何集合,在這個問題:

Collection was not processed by flush when iterate through collection in PostUpdateEvent

你可以試用一下這個答案,以確保它是不是原因

https://stackoverflow.com/a/11575172/1236044


:您的問題

知道觸發錯誤的行會真的有幫助。

又是什麼CloneObjectproperty.SetValue(target, CloneObject(value));

你有沒有試過移動兩條線var value = ...裏面對應的if聲明?這樣你只有在真正需要的時候才能處理這個值。

var value = @event.OldState[i]; 

    if (property.CanWrite && !(@event.Persister.PropertyTypes[i] is CollectionType)) { 
     if (value != null && (@event.Persister.PropertyTypes[i] is ComponentType || @event.Persister.PropertyTypes[i] is EntityType)) 

成爲

if (property.CanWrite && !(@event.Persister.PropertyTypes[i] is CollectionType)) { 
     var value = @event.OldState[i]; 
     if (value != null && (@event.Persister.PropertyTypes[i] is ComponentType || @event.Persister.PropertyTypes[i] is EntityType)) 

var value = property.GetValue(source, null); 

    if (property.CanWrite && (property.PropertyType == typeof(string) || !typeof(IEnumerable).IsAssignableFrom(property.PropertyType)) && !property.PropertyType.IsInterface) { 
     if (value != null && typeof(IEntity).IsAssignableFrom(property.PropertyType)) 

成爲

if (property.CanWrite && (property.PropertyType == typeof(string) || !typeof(IEnumerable).IsAssignableFrom(property.PropertyType)) && !property.PropertyType.IsInterface) { 
     var value = property.GetValue(source, null); 
     if (value != null && typeof(IEntity).IsAssignableFrom(property.PropertyType)) 
+0

謝謝我更新了我的問題。 CloneObject是私有方法的正確名稱。我正在合併來自早期版本的新解決方案,並且錯過了重命名其中一個事件。不過,我已經按照你的說法做了,但問題仍然存在。我用ContentType類編輯了我的問題,該類是我正在更新的實體的屬性。 – nfplee

+0

@nfplee用一些(也許)有趣的鏈接編輯我的答案 – jbl

+0

謝謝我將修補程序應用於IFlushEventListener並清除了此錯誤。然而,我後來又遇到了另一個問題。既然它不是原始問題的一部分,我會將其標記爲答案。謝謝 – nfplee