2011-01-12 61 views
3

請幫我理解這裏發生了什麼,以及它是否應該這樣工作? 我有一個來自CMS的對象的通用列表:奇怪的反射問題 - 無法得到它

例如List<MyCMS.Articles.Article> myArticles = articles.All;

後來我以JSON格式輸出列表的內容(對於CMS UI - 表列表)。

現在單條記錄將包括:

article.Title 
article.Alias 
article.Guid 
article.Description 
+ 
article.SeoProperties.TitleOverride 
article.SeoProperties.H1Tag 
article.StateProperties.IsActive 
article.StateProperties.Channels 

等等

,你可以看到一篇文章對象有一個額外的類屬性 - 具有共同屬性(在其它對象類型使用CMS)

我還使用了過濾器的類,它在收集與LINQ一些過濾操作返回我只有在一定的通道內物品,例如...

所以問題是,當我將集合序列化爲JSON時 - 我真的需要在我的表列表中顯示少量「列」,而我在其他字段中不需要 - 特別是可能需要很長的字段,例如「描述」(從文件系統延遲加載)等 - 我使用DataContractJsonSerializer序列化...

我需要一種方法來控制哪些字段將包含在JSON結果中...我所做的是我如果我不需要該屬性並使用[DataMember(IsRequired = false,EmitDefaultValue = false)]屬性裝飾類屬性,則使用反射將屬性值設置爲null ... - 它應該很好 - 但是 - 只要我去(甚至克隆!!)最終對象的集合去除字段=將值設置爲「null」 - 屬性值變爲空 - 應用程序範圍廣 - 在所有這樣的集合中對象......呃?

在這裏的一些演示代碼:

void Page_Load() { 
     MyCms.Content.Games games = new MyCms.Content.Games(); 
     List<MyCms.Content.Games.Game> allGames = games.All; 

     MyCms.Content.Games games2 = new MyCms.Content.Games(); 
     List<MyCms.Content.Games.Game> allGamesOther = games2.All; 

     Response.Write("Total games: " + allGames.Count + "<br />"); 

     //This is our fields stripper - with result assigned to a new list 
     List<MyCms.Content.Games.Game> completelyUnrelatedOtherIsolated_but_notSureList = RemoveUnusedFields(allGamesOther); 

     List<MyCms.Content.Games.Game> gamesFiltered = allGames.Where(g=>g.GamingProperties.Software=="89070ef9-e115-4907-9996-6421e6013993").ToList(); 

     Response.Write("Filtered games: " + gamesFiltered.Count + "<br /><br />"); 

    } 

    private List<MyCms.Content.Games.Game> RemoveUnusedFields(List<MyCms.Content.Games.Game> games) 
    { 
     List<MyCms.Content.Games.Game> result = new List<MyCms.Content.Games.Game>(); 

     if (games != null && games.Count > 0) 
     { 
      //Retrieve a list of current object properties 
      List<string> myContentProperties = MyCms.Utils.GetContentProperties(games[0]); 

      MyCms.PropertyReflector pF = new MyCms.PropertyReflector(); 

      foreach (MyCms.Content.Games.Game contentItem in games) 
      { 
       MyCms.Content.Games.Game myNewGame = (MyCms.Content.Games.Game)contentItem.Clone(); 
       myNewGame.Images = "wtf!"; //just to be sure we do set this stuff not only null 

       pF.SetValue(myNewGame, "GamingProperties.Software", ""); //set one property to null for testing 

       result.Add(myNewGame); 

      } 
     } 

    return result; 
} 

對象設置爲自己的「默認值」(基本上是零,在大多數情況下)與此:

private object GetDefaultValue(Type type) 
     { 
      if (type.IsValueType) 
      { 
       try 
       { 
        return Activator.CreateInstance(type); 
       } 
       catch { 
        return null; 
       } 
      } 

      return null; 
     } 
+0

如果我沒有記錯的問題,基本上,你設置一個類爲null的屬性的詳細信息,以及其他類別的相同屬性將變爲空。你可以發佈一些代碼嗎?也許在這裏:'我所做的是我使用反射來設置屬性值爲null。'有些東西必須將這些實例互相鏈接起來。您是否設計了「MyCms.Article.Article」對象? – 2011-01-12 13:16:47

+0

是的,我設計的類,得到了完全控制,我不使用任何靜態字段的任何地方...我很容易與您的懷疑同意,就好像屬性在整個類類型的元數據應用越來越設定(將在一會兒發佈一些代碼) – Denis 2011-01-12 13:25:23

+0

Game.Clone()的實現是什麼? – 2011-01-12 13:45:39

回答

2

很可能你在區分淺拷貝和深拷貝時遇到了麻煩。

如果某個字段是值類型,則會執行該字段的逐位拷貝。如果一個字段是一個引用類型,則引用被複制,但引用的對象不是;因此,原始對象及其克隆指的是同一個對象

當您克隆一個對象並且該對象具有引用類型的字段時,使用深層副本創建該對象的新克隆並將其分配給字段(僅引用第一個對象)。因此,你必須完全不同的物體不分享。

這意味着如果您使用的是克隆,並且其中一些屬性實際上是子屬性(即原始對象內的實例的屬性),那麼您將在應用程序範圍內更改它,因爲您正在對參考,而不是該子對象的新實例。

您有關於它

http://msdn.microsoft.com/en-us/library/system.object.memberwiseclone.aspx

0

您可以創建一種模型視圖類的必要字段,並使用像Automapper來填充它們。通過這種方式,您將擁有一個不錯的代碼,易於維護並且可以高度自定義。