c# - 奇怪的反射问题 - 无法得到它

标签 c# json reflection content-management-system setvalue

请帮助我了解这里发生了什么,它是否应该像那样工作? 我有一个来自 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

等...

如您所见,Article 对象有一个额外的类属性 - 具有通用属性(用于 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;
        }

最佳答案

您很可能难以区分浅拷贝和深拷贝。

If a field is a value type, a bit-by-bit copy of the field is performed. If a field is a reference type, the reference is copied but the referred object is not; therefore, the original object and its clone refer to the same object.

当您克隆一个对象并且该对象具有引用类型的字段时,使用深拷贝,该对象的一个​​新克隆被创建并分配给该字段(与仅引用第一个对象相比)。因此,您必须完全不同的对象,它们之间没有任何共享。

这意味着如果您正在使用克隆并且某些属性实际上是子属性(即原始对象内实例的属性),您将在整个应用程序范围内更改它,因为您正在对引用进行操作,不是子对象的新实例。

你有更多关于它的信息

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

关于c# - 奇怪的反射问题 - 无法得到它,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/4668965/

相关文章:

c# - 如何在不安装 Microsoft Lync 的情况下在我的业务应用程序中创建自定义 Lync 客户端?

c# - 有向图顶点子集的拓扑排序

python - 如何从长度为 n 的数组中生成 key

Java:懒加载单例和反射攻击?

c# - 如何连接两个异常?

C# WPF 如何强制执行 Windows 的单个实例

c# - 为什么我不能将 Guid 用作泛型类型约束?

c# - 当对象继承自列表时序列化对象

java - Jackson 映射到 POJO 无法反序列化实例实例

c# - 如何使用反射获取泛型类型的扩展方法