代码之家  ›  专栏  ›  技术社区  ›  Maslow

我可以使用javascriptserializer反序列化为不可变对象吗?

  •  4
  • Maslow  · 技术社区  · 14 年前

    使用 System.Web.Script.Serialization.JavaScriptSerializer

    我能以某种方式反序列化为不可变对象吗?

       public class Item
    {
        public Uri ImageUri { get;private set; }
        public string Name { get; private set; }
        public Uri ItemPage { get;private set; }
        public decimal Retail { get;private set; }
        public int? Stock { get; private set; }
        public decimal Price { get; private set; }
    
    
        public Item(Uri imageUri, string name, Uri itemPage, decimal retail, int? stock, decimal price)
        {
            ImageUri = imageUri;
            Name = name;
            ItemPage = itemPage;
            Retail = retail;
            Stock = stock;
            Price = price;
        }
    }
    

    约束:我不想要一个公共的空构造函数,我不想将所有内容都更改为可变的,我不想使用XML代替JSON。

    2 回复  |  直到 12 年前
        1
  •  7
  •   Carl    12 年前

    我必须找到答案,因为这是谷歌的第一个结果,但它没有给出一个例子,我决定分享我的想法(基于詹姆斯·埃利斯·琼斯提供的链接)。

    我的情况是我需要一个“金钱”对象是不变的。我的货币对象需要一个金额和一个货币。必须是不可变的,因为我使用它的时候就像用十进制值替换它一样(类似于货币值支持的数学运算),我需要传递它,而不必担心是通过引用传递还是复制传递。

    因此,我在这里实现了javascriptconverter:

    public class MoneyJsonConverter : JavaScriptConverter
    {
    
        public override object Deserialize(IDictionary<string, object> dictionary, Type type, JavaScriptSerializer serializer)
        {
            if (dictionary == null)
                throw new ArgumentNullException("dictionary");
    
            if (type != typeof(Money))
                return null;
    
            var amount = Convert.ToDecimal(dictionary.TryGet("Amount"));
            var currency = (string)dictionary.TryGet("Currency");
    
            return new Money(currency, amount);
        }
    
        public override IDictionary<string, object> Serialize(object obj, JavaScriptSerializer serializer)
        {
            var moneyAmount = obj as Money;
            if (moneyAmount == null)
                return new Dictionary<string, object>();
    
            var result = new Dictionary<string, object>
                {
                    { "Amount", moneyAmount.Amount },
                    { "Currency", moneyAmount.Currency },
                };
            return result;
        }
    
        public override IEnumerable<Type> SupportedTypes
        {
            get { return new ReadOnlyCollection<Type>(new List<Type>(new[] { typeof(Money) })); }
        }
    }
    

    然后,我通过web.config文件向javascriptserializer注册了转换器:

    <system.web.extensions>
        <scripting>
            <webServices>
                <jsonSerialization>
                    <converters>
                        <add name="MoneyConverter" type="My.Namespace.MoneyJsonConverter, MyAssembly, Version=1.0.0.0, Culture=neutral"/>
                    </converters>
                </jsonSerialization>
            </webServices>
        </scripting>
    </system.web.extensions>
    

    就是这样!不过,我也用几个属性来装饰我的班级:

    [Serializable]
    [Immutable]
    public class Money
    
        2
  •  0
  •   James Ellis-Jones    13 年前

    JavaScriptSerializer提供自定义API,您可以创建从JavaScriptConverter继承的类,以指定如何从字典中构建项类,然后在JavaScriptSerializer实例上使用RegisterConverters方法注册自定义转换器。

    definition of javascriptserializer.registerconverters