我只是在学习WCF服务。我有一个方法返回我创建的名为GPSPosition的对象。 GPS位置对象具有纬度和经度。没有这些属性,对象永远不应该存在。所以,我想让构造函数接受Lat和Long浮点数。因此,在创建对象时,将设置值,并且永远不会无效(取消设置)。
但是,它是我的WCF服务的一个对象。可以作为我的调用应用程序使用的WCF服务对象有一个构造函数吗?如果我在调用代码中var position = new GpsPosition{ lat=1, lon=1 };
,构造函数是否可以工作?你能在WCF类中拥有构造函数吗?
我认为它们是在不同语言之间共享的 - 所以如果Java使用该服务,例如,我不确定构造函数将如何触发。对象结构与调用应用共享,不是吗?你可以在构造函数中启动.net代码(对于那种情况,还有getter和setter方法)?
如果构造函数不可用 - 有没有办法确保我的对象永远无效? (必须在-180和+180之间有有效的纬度/经度值?)
答案 0 :(得分:6)
答案取决于您的类型GpsPosition
使用的序列化模型。 WCF中使用的两个最常见的是POCO(普通旧CLR对象)和[DataContract]
。在前者中,对象必须具有无参数构造函数,这违背了您的要求(值需要设置一次)。在后者中,不调用对象构造函数 - 而是创建该类型的未初始化实例,并通过反序列化设置其成员。
因此,构造函数不是验证来自线路的对象的替代方法。验证对象而不是构造函数所需的是序列化回调,在反序列化完成时调用它。反序列化完成后,WCF序列化程序将调用它们,您可以检查对象是否已正确初始化,否则抛出异常。这个blog post提供了有关序列化回调的更多详细信息,下面的代码显示了您的方案的一种可能实现。
[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");
}
}
}