代码之家  ›  专栏  ›  技术社区  ›  John Farrell

属性只能由序列化程序设置

  •  3
  • John Farrell  · 技术社区  · 14 年前

    我有一个类,它与API通信,需要对它接触到的任何数据进行一些转换。这个类也是等价的:

    public class SerializeMe
    {
        public SerializeMe(string someString)
        {
            _someString = someString;
        }
    
        private string _someString;
        public string TransformedValue
        {
            get { _someString = TransformToSomething();
                  return _someString; }
            set { _someString = value; }
        }
    }
    

    对于我的API调用程序,我通过序列化这些类来记录每个请求和响应。它们几乎充当XML模式。

    现在一切都很好,我唯一的问题是,理论上,有人可能会尝试设置,但最终无法获得预期的结果。这主要是一个设计问题,只是想让我的代码负责。我很想在这个上面使用一个私有集,但是XML序列化程序抱怨它。

    是否有属性或其他技术能够使转换后的值不可设置(序列化程序除外)?

    此外,如果没有选项,则将属性设为已过时是一个选项。还有其他更合适的属性可以使用吗?

    3 回复  |  直到 14 年前
        1
  •  2
  •   Marc Gravell    14 年前

    这是XMLSerializer的一个难题,但可以使用DataContractSerialzer(它也可以在没有XMLSerializer需要的无参数ctor的情况下工作)。只需将类型标记为[数据合同],然后 领域 (非属性)作为[数据成员]。

    [DataContract]
    public class SerializeMe
    {
        public SerializeMe(string someString)
        {
            _someString = someString;
        }
        [DataMember]
        private string _someString;
        public string TransformedValue
        {
            get { _someString = TransformToSomething();
                  return _someString; }
            private set { _someString = value; }
        }
    }
    
        2
  •  2
  •   Bronumski    14 年前

    XMLSerializer做了很多现成的工作,但是为了获得灵活性,您应该在使用 IXmlSerializable 接口。XmlSerializer将查看该对象,如果它实现了IXMLSerializable,它将调用接口公开的对象上的方法。是的,这是更多的工作,但是对于如何对对象进行反/序列化,您有一个更细粒度的方法。

        3
  •  0
  •   Marc Gravell    14 年前

    不幸的是,XmlSerializer只能使用公共getter/setter对属性进行序列化(当然,除非通过 IXmlSerializable )

    我不时使用的唯一解决方法(这是一种黑客方法,不符合.NET设计准则,因此我根本不喜欢这样做)是使用一个带有空setter的公共属性,然后使用另一种方法来设置私有支持变量:

    public class SerializeMe
    {
        private string _someString;
        public string SomeString
        {
            get
            {
                _someString = TransformToSomething();
                return _someString;
            }
            set { }
        }
    
        public void SetString(string val) { _someString = val; }
    }
    

    明显地 IXML可序列化 是更多的工作,但从长远来看,这绝对是一个更好的决定(更不用说这不是一个黑客)。