请帮助我了解这里发生了什么以及它是否应该像那样工作?
我有一个来自 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 执行一些过滤操作,以仅返回某个 channel 中的文章,例如...
所以问题是,当我将集合序列化为 JSON 时 - 我真正需要在我的表列表中显示的只有几个“列”,而我在其他字段中不需要 - 特别是可能很长的字段,例如“描述“(从文件系统延迟加载)等... - 我使用 DataContractJsonSerializer 进行序列化...
我需要一种方法来控制哪些字段将包含在 JSON 结果中...我所做的是使用反射将属性值设置为 null 如果我不需要该属性并且
用 [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;
}
最佳答案
很可能您在区分浅拷贝和深拷贝时遇到了麻烦。
当您克隆一个对象并且该对象具有引用类型的字段时,使用深度复制,会创建该对象的新克隆并将其分配给该字段(而不是仅引用第一个对象)。因此,您必须完全不同的对象,它们不共享任何内容。
这意味着如果您使用 clone 并且某些属性实际上是子属性(即原始对象内实例的属性),您正在应用程序范围内更改它,因为您是根据引用而不是新的子对象的实例。
你有更多关于它的信息
http://msdn.microsoft.com/en-us/library/system.object.memberwiseclone.aspx
关于c# - 奇怪的反射问题 - 无法解决,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/4668965/