WCF --KnowType,ServiceKnownType,配置文件添加

KnowType

指定 DataContractSerializer 在序列化和反序列化给定类型时应识别的类型

ServiceKnownType

指定序列化或反序列化时服务要使用的已知类型


父类:

 
namespace Contracts.Model
{
    //[KnownType(typeof(ChildModel))]
    public class ParentModel
    {
        public string PName { get; set; }
 
        public int Age { get; set; }
 
    }
}


派生类:

namespace Contracts.Model
{
    public class ChildModel:ParentModel
    {
        public string CName { get; set; }
 
    }
}

服务契约:

using System.Collections.Generic;
using System.ServiceModel;
using Contracts.Model;
 
namespace Contracts
{
    [ServiceContract]
    //[ServiceKnownType(typeof(ChildModel))]
    public interface IContract
    {      
        [OperationContract]
        //[ServiceKnownType(typeof(ChildModel))]
        ParentModel ChildToParent();
 
    }

服务端实现:

using System.Collections.Generic;
using Contracts;
using Contracts.Model;
 
namespace Serices
{
    public class ServiceImpl : IContract
    {   public ParentModel ChildToParent()
        {
            ChildModel cinfo = new ChildModel();
            cinfo.Age = 123;
            cinfo.CName = "子类";
            cinfo.PName = "P1";
            return cinfo;
        }
    }
}


服务端config

<?xml version="1.0" encoding="utf-8" ?>
<configuration>
  <system.serviceModel>
    <bindings>
      <netTcpBinding>
        <binding name="CatorNetTcpBing" receiveTimeout ="00:00:40" >
          <!--<reliableSession ordered="true" inactivityTimeout="00:00:10"  enabled="false" />-->
        </binding>
      </netTcpBinding>
    </bindings>
    <behaviors>
      <serviceBehaviors>
        <behavior name="metadataBehavior">
          <serviceDebug includeExceptionDetailInFaults ="false"/>
        </behavior>
      </serviceBehaviors>
    </behaviors>
    <services>
      <service behaviorConfiguration="metadataBehavior" name="Serices.ServiceImpl">
        <endpoint address="net.tcp://192.168.1.204:9300/IContract" binding="netTcpBinding"
          contract="Contracts.IContract" bindingConfiguration ="CatorNetTcpBing" />
      </service>
    </services>
  </system.serviceModel>
  <system.diagnostics>
    <trace autoflush="true" />
    <sources>
      <source name="System.ServiceModel"
              switchValue="Error"
              propagateActivity="true">
        <listeners>
          <add name="xwt"
                   type="System.Diagnostics.XmlWriterTraceListener"
                   initializeData="MyListener.log"  />
        </listeners>
      </source>
    </sources>
  </system.diagnostics>
  <!--<system.runtime.serialization>
    <dataContractSerializer>
      <declaredTypes>
        <add type="Contracts.Model.ParentModel, Contracts, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null">
          <knownType type="Contracts.Model.ChildModel, Contracts, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null" />
        </add>
        </declaredTypes>
    </dataContractSerializer>
  </system.runtime.serialization>-->
</configuration>


客户端调用:

using System.Collections.Generic;
using System.ServiceModel;
using Contracts.Model;
 
namespace Contracts.Client
{
    public class ClientImpl:ClientBase<IContract>,IContract
    {      
        public ParentModel ChildToParent()
        {
            return Channel.ChildToParent();
        }
    }
}


客户端CONFIG

<?xml version="1.0" encoding="utf-8"?>
<configuration>
    <system.serviceModel>
        <bindings>
            <netTcpBinding>
                <binding name="CatorNetTcpBing" receiveTimeout="00:00:40" />
            </netTcpBinding>
        </bindings>
        <client>
            <endpoint address="net.tcp://192.168.1.204:9300/IContract" binding="netTcpBinding"
                bindingConfiguration="CatorNetTcpBing" contract="Contracts.IContract"
                name="" kind="" endpointConfiguration="">
            </endpoint>
        </client>
        <services />
    </system.serviceModel>
  <!--<system.runtime.serialization>
    <dataContractSerializer>
      <declaredTypes>
        <add type="Contracts.Model.ParentModel, Contracts, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null">
          <knownType type="Contracts.Model.ChildModel, Contracts, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null" />
        </add>
      </declaredTypes>
    </dataContractSerializer>
  </system.runtime.serialization>-->
</configuration>


1.在父类CLASS上写 [KnownType(typeof(ChildModel))]

2.在服务接口(interface)或定义的某个规则上加[ServiceKnownType(typeof(ChildModel))]

3.在客户端和服务端上同时加相关配置

作用:实现继承,子类往父亲转换,从而实现多态


另一个例子:


1.服务器端:

/// <summary>
    /// 实现IExtensibleDataObject接口,表示这个类的派生类也可以序列化
    /// IsRequired表示该属性是否需要赋值之后才能序列化
    /// 
    /// 注意:此类上没有标记KnownType属性,于是在客户端找不到School的派生类
    /// 若是在此类上没有KnownType标记,在契约接口上使用ServiceKnownType标记也是可以的
    /// 当然,ServiceKnownType标记也是可以应用在接口里面的方法上面的
    /// </summary>
    [DataContract(Name = "SchoolEntity", Namespace = "http://schemas.yoyo/zhu")]
    //[KnownType(typeof(Teacher))]
    //[KnownType(typeof(Student))]
    public class School : IExtensibleDataObject
    {
        /// <summary>
        /// 学校编号
        /// </summary>
        [DataMember(Name = "Num", IsRequired = true, Order = 0)]
        public string s_Num { get; set; }
        /// <summary>
        /// 学校名称
        /// </summary>
        [DataMember(Name = "Name", IsRequired = true, Order = 1)]
        public string s_Name { get; set; }
        /// <summary>
        /// 描述
        /// </summary>
        [DataMember(Name = "Description", IsRequired = false, Order = 2)]
        public string s_Description { get; set; }

        private ExtensionDataObject extensionDataObject;
        #region IExtensibleDataObject 成员
        public ExtensionDataObject ExtensionData
        {
            get
            {
                return extensionDataObject;
            }
            set
            {
                extensionDataObject = value;
            }
        }
        #endregion
    }
派生类:
    [DataContract(Namespace = "http://schemas.yoyo/zhu")]
    public class Student : School
    {
        public Student()
        {
            this.s_SchoolDerivedClass = SchoolEnmu.Student;
        }
    }
    [DataContract(Namespace = "http://schemas.yoyo/zhu")]
    public class Teacher : School
    {
        public Teacher()
        {
            this.s_SchoolDerivedClass = SchoolEnmu.Teacher;
        }
    }

2.契约

 [ServiceContract(Name = "IKonwTypeService", Namespace = "http://www.yoyo/zhu")]
    [ServiceKnownType(typeof(Teacher))]
    [ServiceKnownType(typeof(Student))]
    public interface IKonwTypeService
    {
        [OperationContract]
        void AddTeacher(School sc);
        [OperationContract]
        List<School> GetTeacher();
    }
    //这个ServiceBehavior可有可无
    //[ServiceBehavior(InstanceContextMode = InstanceContextMode.PerSession)]
    public class KonwTypeService : IKonwTypeService
    {
        private static School school;
        #region IKonwTypeService 成员
        public void AddTeacher(School sc)
        {
            school = sc;
        }
        public List<School> GetTeacher()
        {
            List<School> list = new List<School>();
            list.Add(school);
            return list;
        }
        #endregion
    }

3.宿主环境配置:

    ServiceHost host = new ServiceHost(typeof(KonwTypeService));
            host.Open();
            Console.WriteLine("宿主服务已启动!");
            Console.ReadKey();
  <system.serviceModel>
    <services>
      <service name="KonwTypeServices.KonwTypeService" behaviorConfiguration="serviceBehavior">
        <host>
          <baseAddresses>
            <add baseAddress="http://localhost:8044"/>
          </baseAddresses>
        </host>
        <endpoint address="KonwTypeService" contract="KonwTypeServices.IKonwTypeService" binding="basicHttpBinding" />
        <endpoint contract="IMetadataExchange" binding="mexHttpBinding" address="mex" />
      </service>
    </services>
    <behaviors>
      <serviceBehaviors>
        <behavior name="serviceBehavior">
          <serviceMetadata httpGetEnabled="true"/>
        </behavior>
      </serviceBehaviors>
    </behaviors>
  </system.serviceModel>

4.客户端


5.注意:当ServiceKnownType和KnownType标记都没使用时,可以在配置文件里面添加如下代码,在客户端也能生成其派生类


<system.runtime.serialization>
  <dataContractSerializer>
    <declaredTypes>
      <add type="EntityModel.School, EntityModel, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null">
        <knownType type="EntityModel.Student, EntityModel, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null" />
        <knownType type="EntityModel.Teacher, EntityModel, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null" />
      </add>
    </declaredTypes>
  </dataContractSerializer>
  </system.runtime.serialization>

小结:

KnowType表示:在WCF中一个继承类可以转换成其父类,加上这个标签后,父类也可以转成子类,从而保留多态性。同时,客户端还不会生成子类的相应信息。
ServiceKnowType:当提供的服务中有参数是上面提及的父类,为了把这个父类的派生类带出来,于是需要在接口上面使用ServiceKnowType指定其派生类。当只需要在某个方法上面使用该父类的派生类,就可

以在该方法的上面使用ServiceKnowType指定即可。
在WCF中,继承的接口和类是反映不到客户端的,因此说WCF牺牲了OO的继承和多态的特性。但是这种特性可以使用已知类型的方式弥补。

 

源代码下载地址:http://download.csdn.net/detail/yoyoshaoye/3614453


本文出自勇哥的网站《少有人走的路》wwww.skcircle.com,转载请注明出处!讨论可扫码加群:
本帖最后由 勇哥,很想停止 于 2024-06-21 16:52:13 编辑

发表评论:

◎欢迎参与讨论,请在这里发表您的看法、交流您的观点。

会员中心
搜索
«    2025年4月    »
123456
78910111213
14151617181920
21222324252627
282930
网站分类
标签列表
最新留言
    热门文章 | 热评文章 | 随机文章
文章归档
友情链接
  • 订阅本站的 RSS 2.0 新闻聚合
  • 扫描加本站机器视觉QQ群,验证答案为:halcon勇哥的机器视觉
  • 点击查阅微信群二维码
  • 扫描加勇哥的非标自动化群,验证答案:C#/C++/VB勇哥的非标自动化群
  • 扫描加站长微信:站长微信:abc496103864
  • 扫描加站长QQ:
  • 扫描赞赏本站:
  • 留言板:

Powered By Z-BlogPHP 1.7.2

Copyright Your skcircle.com Rights Reserved.

鄂ICP备18008319号


站长QQ:496103864 微信:abc496103864