2009-11-11 72 views
1

原諒我,如果這已被問及;經過幾次搜索後我找不到任何東西:迭代未知的IQueryable屬性?

我正在嘗試在MVC中編寫ActionFilter,它將「攔截」IQueryable並在運行時取消所有父子關係。我這樣做是因爲Linq沒有正確序列化對象,如果他們有父 - 子關係(由於父引用的是父引用的子引用等引發的循環引用錯誤),我需要該對象序列化爲Json進行Ajax調用。我試圖在DBML文件中標記具有內部隱私狀態的子關係,並在修復序列化問題的同時,還在頁面呈現時從視圖引擎中隱藏子成員,導致引發另一個錯誤。所以,通過解決一個問題,我會造成另一個問題。

解決這兩個問題的唯一方法是在返回序列化之前手動將子成員設置爲null,但我試圖避免這樣做,因爲它很麻煩,不可重用等。我寧願使用ActionFilter檢查正在序列化的IQueryable,並使用Type of EntitySet(表示外鍵/關聯如何表示)取消任何成員。但是,我對Reflection沒有太多經驗,並且找不到任何示例來說明如何執行此類操作。所以...這可能與反思?有沒有更好的方法來完成同樣的事情?明天當我回到工作計算機時,我會發布相關代碼。

感謝,

丹尼爾


如所承諾的,代碼:

[GridAction] 
public ActionResult _GetGrid() 
{ 
    IQueryable<Form> result = formRepository.GetAll(); 
    foreach (Form f in result) 
    { 
     f.LineItems = null; 
     f.Notes = null; 
    } 

    return View(new GridModel<Form> { Data = result }); 
} 

一個額外的皺紋是,我使用的新Telerik的MVC擴展,所以我實際上並不是實際序列化Json - 我只是在IGridModel中返回IQueryable,而其餘的部分則是動作過濾器[GridAction]。

回答

0

有兩種選擇,一種是在使用[XmlIgnore]的序列化過程中忽略這些屬性。另一個是使用反射來使屬性無效。

忽略系列化,演示如何在序列化使用默認值,簡單的用法示例:

[Serializable] 
public class MyClass 
{ 
    [XmlIgnore] 
    public int IgnoredVal { get; set; } 

    public int Val { get; set; } 
} 

public void UsageSample() 
{ 
    var xmlSerializer = new XmlSerializer(typeof(MyClass)); 
    var memoryStream = new MemoryStream(); 
    var toSerialize = new MyClass { IgnoredVal = 1, Val = 2 }; 
    xmlSerializer.Serialize(memoryStream, toSerialize); 
    memoryStream.Position = 0; 
    var deserialize = (MyClass)xmlSerializer.Deserialize(memoryStream); 

    Assert.AreEqual(0, deserialize.IgnoredVal); 
    Assert.AreEqual(2, deserialize.Val); 
} 

廢除與反思,代碼示例:

public void NullifyEntitySetProperties(object obj) 
{ 
    var entitySetProperties = obj.GetType().GetProperties() 
     .Where(property => property.PropertyType == typeof(EntitySet)); 

    foreach (var property in entitySetProperties) 
    { 
     property.SetValue(obj, null, null); 
    } 
} 

在我看來,如果第一個選項可以在你的代碼中使用,那就更好了。這個選項更直接和經濟。

1

所以,爲了萬一有人好奇,下面是我最終解決了這個問題的方法:我修改了Damien Guard的T4模板,將屬性[ScriptIgnore]包含在Association類型的實體之上。這讓JSON序列化器知道不打擾序列化這些,從而防止我得到的循環引用問題。生成的代碼最終看起來像這樣:

private EntitySet<LineItem> _LineItems; 
    [ScriptIgnore] 
    [Association([email protected]"Form_LineItem", [email protected]"_LineItems", [email protected]"Id", [email protected]"FormId")] 
    public EntitySet<LineItem> LineItems 
    { 
     get { 
      return _LineItems; 
     } 
     set { 
      _LineItems.Assign(value); 
     } 
    } 

這修復我是有序列化的問題,而無需通過LINQ禁止使用童工表。控制器上的電網動作最終看起來像這樣:

[GridAction] 
public ActionResult _GetGrid() 
{ 
    return View(new GridModel<Form> { Data = formRepository.GetAll() }); 
}