WCF类型和ServiceKnowType之间的差异



考虑以下两个数据契约:

[DataContract]    
public class Item
{
    [DataMember]
    public int X;
}
[DataContract]
public class SubItem : Item
{
    [DataMember]
    public int Y;
}

在以下服务合同中使用这两个数据合同有什么区别。

[ServiceContract]
public interface IInterface
{
    [OperationContract]
    [ServiceKnownType(typeof(SubItem))]
    void Save(Item i);
}
[ServiceContract]
public interface IInterface
{
    [OperationContract]
    void Save(SubItem i);
}

第一个可以用SubItem以外的项的子类调用吗?如果是,那么ServiceKnownType的含义是什么?

在第一种情况下使用时,假设SubItem继承自Item,则当Web服务公开其WSDL时,您会告诉Web服务考虑SubItem类型的反序列化,因为它可能被用作Item参数(多态性主体)的参数,否则,即使DataMemberAttribute在客户端对类型进行了反序列化,接收方端点也将无法将SubItem作为方法的参数进行传递。

应用了ServiceKnownTypeNote,即使SubItem没有用DataMember属性标记,该类也将被序列化

这里是的一个例子

服务端

using System.Runtime.Serialization;
using System.ServiceModel;
namespace WcfService1
{
    [ServiceContract]
    public interface IService1
    {
        [OperationContract]
        [ServiceKnownType(typeof(SubItem))] // try to comment this and uncomment GetDataUsingDataContract 
         Item GetData(int value);
        //[OperationContract] //here try to comment/uncomment and see if the subitem was deserialized at client side the operation on server side will not be executed 
        //Item GetDataUsingDataContract(SubItem item);
        //// TODO: Add your service operations here
    }

    // Use a data contract as illustrated in the sample below to add composite types to service operations.
    [DataContract]
    public class Item
    {
        bool boolValue = true;
        string stringValue = "Hello ";
        [DataMember]
        public bool BoolValue
        {
            get { return boolValue; }
            set { boolValue = value; }
        }
        [DataMember]
        public string StringValue
        {
            get { return stringValue; }
            set { stringValue = value; }
        }
    }
    //[DataContract]
    public class SubItem:Item
    {
        private string _subItemVersion;
        //[DataMember]
        public string SubItemToStringValueVersion { get { return _subItemVersion; } set { _subItemVersion = value; } }
    }
}

客户端

  static void Main(string[] args)
        {
            Service1Client service1Client =  new Service1Client();
             var result  = service1Client.GetData(5);
            if (result is SubItem)
            {
            }
        }

是的,可以调用第一个,但如果实际类型对服务未知,则只能使用Item类型中的成员。

在这种情况下,ServiceKnownType对服务器没有任何用途/意义,因为它既没有用于参数也没有用于返回类型。

例如,如果Save操作将返回一个Item,而实际项是一个子项,则它将把结果序列化为一个子项。这就是ServiceKnownType属性的作用。

第一个Save方法只能用ItemSubIteminstance调用,但第二个方法只接受SubItem

ServiceKnownTypeAttribute的目的是指定反序列化过程中应考虑的类型。有关更多信息,请参阅数据协定已知类型和ServiceKnownTypeAttribute类

在以下服务契约中使用这两个数据契约有什么区别?使用第一个,您可以传入类型为Item或SubItem的对象,因为SubItem公开为KnowType。在第二个中,您只能传递SubItem类型的项。

第一个可以用SubItem以外的项的子类调用吗?如果是,那么ServiceKnownType的含义是什么?否,不能用SubItem以外的项的子类调用它。要做到这一点,您必须将其作为KnownType公开。

最新更新