3

我只是在学习 WCF 服务。我有一个方法可以返回我创建的名为 GPSPosition 的对象。GPS 位置对象具有纬度和经度。如果没有这些属性,该对象永远不会真正存在。所以,我想让构造函数接受 Lat 和 Long 浮点数。所以当对象被创建时,值是被设置的,并且永远不会是无效的(Unset)。

但是,它是我的 WCF 服务的一个对象。我的调用应用程序使用的 WCF 服务对象可以具有构造函数吗?如果我var position = new GpsPosition{ lat=1, lon=1 };在我的调用代码中,构造函数会工作吗?WCF 类中可以有构造函数吗?

我认为它们在不同的语言之间共享 - 例如,如果 Java 使用该服务,我不确定构造函数将如何触发。对象结构共享给调用应用程序,不是吗?您可以在构造函数中触发 .net 代码吗(在这种情况下,还有 getter 和 setter 方法)?

如果构造函数不可用 - 有没有办法确保我的对象永远不会无效?(必须具有介于 -180 和 +180 之间的有效纬度/经度值)?

4

1 回答 1

6

答案将取决于您的类型GpsPosition使用的序列化模型。WCF 中最常用的两个是 POCO(普通 CLR 对象)和[DataContract]. 在前者中,对象必须有一个无参数的构造函数,这违背了您的要求(值需要设置一次)。在后者中,不调用对象构造函数——而是创建了一个未初始化的类型实例,并通过反序列化设置其成员。

因此,构造函数不是验证来自网络的对象的​​替代方法。您需要验证对象而不是构造函数的是序列化回调,它在反序列化完成时调用。WCF 序列化程序将在反序列化完成时调用它们,您可以在那里检查对象是否已正确初始化,否则抛出异常。这篇文有更多关于序列化回调的详细信息,下面的代码显示了您的场景的一种可能实现。

[DataContract]
public class GpsPosition
{
    private float _lat;
    private float _lon;
    private bool _latWasSet;
    private bool _lonWasSet;

    public GpsPosition(float lat, float lon)
    {
        _lat = lat;
        _lon = lon;
    }

    [DataMember]
    public float lat
    {
        get { return _lat; }
        private set
        {
            _lat = value;
            _latWasSet = true;
        }
    }

    [DataMember]
    public float lon
    {
        get { return _lon; }
        private set
        {
            _lon = value;
            _lonWasSet = true;
        }
    }

    [OnDeserialized]
    void OnDeserialized(StreamingContext ctx)
    {
        if (!_latWasSet || _!lonWasSet ||
            _lat < -90 || _lat > 90 ||
            _lon < -180 || _lon > 180)
        {
            throw new InvalidOperationException("Required property is missing");
        }
    }
}
于 2013-03-22T15:18:16.743 回答