在WCF调用中同样可以使用面向对象的继承与多态,但是由于WCF不同于进程间调用,其解决方法也有其特殊性。
1、例子
客户端可以向服务器传递操作命令,但是每个操作命令会有各自的命令参数,从面向对象的角度来讲,这种设计需要有一个基类的命令参数,然后每一个命令有相应命令参数子类,我们同样用这种思想来设计WCF contract.
2、实现
操作数据契约定义如下:
[DataContract]
public class DeviceOperation
{
[DataMember]
public OperationType Type { get; set; }
[DataMember]
public OperationArgs Args { get; set; }
[DataMember]
public string DeviceID { get; set; }
}
其中OperationArgs是所有操作参数的基类。
[DataContract]
[KnownType(typeof(PowerOnAndPowerOffTimeOperationArgs))]
[KnownType(typeof(SettingDeviceTimeOperationArgs))]
[KnownType(typeof(SettingRefreshIntervalOperationArgs))]
[KnownType(typeof(SettingVolumeOperationArgs))]
[KnownType(typeof(BusinessControlOperationArgs))]
[KnownType(typeof(UpgradeOperationArgs))]
public class OperationArgs
{
}
这里的关键点就在于KnownType,如果没有KnownType标签,当向DeviceOperation的Args属性赋值一个OperationArgs子类的对象会因为DataContractSerializer找不到子类而序列化失败。
其中一个参数子类的设计如下:
[DataContract]
public class PowerOnAndPowerOffTimeOperationArgs : OperationArgs
{
[DataMember]
public DateTime PowerOnTime { get; set; }
[DataMember]
public DateTime PowerOffTime { get; set; }
}
3、使用
经过如上的设计,我们就可以使用习惯的多态方式来对参数进行赋值:
List<DeviceOperation> operations = new List<DeviceOperation>();
SelectedDevice
.ForEach(item => operations.Add(new DeviceOperation()
{
DeviceID = item,
Type = OperationType.SettingVersionUpdate,
Args = new PowerOnAndPowerOffTimeOperationArgs()
{
PowerOnTime = TimeSelector5.Date,
PowerOffTime = TimeSelector6.Date
}
}));
client.AddDeviceOperation(operations);