的JavaScriptSerializer序列化属性两次当"新"在子类中使用 [英] JavascriptSerializer serializing property twice when "new" used in subclass

查看:191
本文介绍了的JavaScriptSerializer序列化属性两次当"新"在子类中使用的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

试图建立一个服务来回报有许多共同属性的对象,而是一个属性应在某些情况下被高度限制。这是导致奇数和意外的行为,其中一个属性名称序列化输出重用,从而在浏览器中不正确的行为。这里是一个可以(如果你加入 System.Web.Extensions程序的引用),看问题被粘贴到LINQPad一个例子:

Trying to create a service to return an object that has many shared properties, but one property should be highly limited in some situations. This is resulting in odd and undesired behaviour, where a property name is reused in the serialized output, resulting in incorrect behaviour in the browser. Here is an example that can be pasted into LINQPad (if you add a reference to System.Web.Extensions) to see the problem:

void Main()
{
    System.Web.Script.Serialization.JavaScriptSerializer json = new System.Web.Script.Serialization.JavaScriptSerializer();

    json.Serialize(new Full(true)).Dump();
    json.Serialize(new Limited()).Dump();
}

public class Full
{
    public String Stuff { get { return "Common things"; }  }
    public FullStatus Status { get; set; }

    public Full(bool includestatus)
    {
        if(includestatus)
            Status = new FullStatus();
    }
}

public class Limited : Full
{
    public new LimitedStatus Status { get; set; }

    public Limited() : base(false)
    {
        Status = new LimitedStatus();
    }
}

public class FullStatus 
{
    public String Text { get { return "Loads and loads and loads of things"; } }
}

public class LimitedStatus 
{
    public String Text { get { return "A few things"; } }
}

这将显示:

{"Stuff":"Common things","Status":{"Text":"Loads and loads and loads of things"}}
{"Status":{"Text":"A few things"},"Stuff":"Common things","Status":null}

当JSON.parse是所谓的浏览器,第二个状态将覆盖第一,这意味着状态始终为null。

When JSON.parse is called in the browser, the second Status overrides the first, meaning Status is always null.

只有这样,我可以看到解决这个的是从一个共同的父重构,使FullStatus和LimitedStatus都继承并使用覆盖宁可 - 有点复杂在现实世界中的代码,但可能的。是我的假设是正确的?还有,我很想知道这是预期的行为,或有bug。

The only way I can see of fixing this is to refactor so that FullStatus and LimitedStatus both inherit from a common parent and use override rather that new - bit more complicated in the real world code, but possible. Is my assumption correct? And also, I'd be interested to know if this is expected behaviour or a bug.

推荐答案

是的,你的假设是正确的。在关键字是不一样的覆盖;它仅仅是隐藏基类的属性,但原产权仍然存在,仍然可以通过反射发现(这是串行怎么做他们的工作)。

Yes, your assumption is correct. The new keyword is not the same as override; it merely "hides" the base class property, but the original property is still there and can still be discovered via reflection (which is how serializers do their work).

一般,它被认为是码味来定义基类的方法或属性,然后在派生类中夺基类的功能的另一个方法或属性替换它。这违反了里氏替换原则

Generally, it is considered a "code smell" to define a method or property in a base class and then replace it with another method or property in a derived class that takes away functionality of the base class. This violates the Liskov Substitution Principle.

相反得出有限公司全部的,我建议你做一个抽象基类,他们把普通东西在里面。然后,您可以添加一些东西给每个子类都不同或专门给每个(即你的不同类型的状态成员)。

Instead of deriving Limited from Full, I would propose that you make an abstract base class for them and put the common stuff in there. Then, you can ADD things to each subclass which are different or exclusive to each (i.e. your differently-typed Status members).

例如:

class Program
{
    static void Main(string[] args)
    {
        System.Web.Script.Serialization.JavaScriptSerializer json = 
            new System.Web.Script.Serialization.JavaScriptSerializer();

        Console.WriteLine(json.Serialize(new Full(true)));
        Console.WriteLine(json.Serialize(new Limited()));
    }
}

public abstract class Base
{
    public String Stuff { get { return "Common things"; } }
}

public class Full : Base
{
    public FullStatus Status { get; set; }

    public Full(bool includestatus)
    {
        if (includestatus)
            Status = new FullStatus();
    }
}

public class Limited : Base
{
    public LimitedStatus Status { get; set; }

    public Limited()
    {
        Status = new LimitedStatus();
    }
}

public class FullStatus
{
    public String Text { get { return "Loads and loads and loads of things"; } }
}

public class LimitedStatus
{
    public String Text { get { return "A few things"; } }
}



输出:

Output:

{"Status":{"Text":"Loads and loads and loads of things"},"Stuff":"Common things"}
{"Status":{"Text":"A few things"},"Stuff":"Common things"}

这篇关于的JavaScriptSerializer序列化属性两次当"新"在子类中使用的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆