代码之家  ›  专栏  ›  技术社区  ›  Dai

我的目标是否可以使用WCF(这是正确的方法吗?)

  •  1
  • Dai  · 技术社区  · 14 年前

    我正在编写一些修改Windows服务器配置的软件(如MS-DNS、IIS、文件系统的一部分)。我的设计有一个服务器进程,它构建一个服务器配置状态的内存中对象图和一个请求这个对象图的客户机。然后,服务器将序列化图形,将其发送到客户机(可能使用WCF),然后服务器对该图形进行更改并将其发送回服务器。服务器接收图形并继续对服务器进行修改。

    然而,我了解到,在WCF中对象图序列化并不像我最初想象的那样简单。我的对象具有层次结构,许多对象具有参数化的构造函数和不可变的属性/字段。还有许多集合、数组和字典。

    我对WCF序列化的理解是,它需要使用XmlSerializer或DataContractSerializer,但DCS对我的对象图的设计进行了限制(不可变的数据似乎是正确的,它还需要无参数的构造函数)。我理解XMLSerializer允许我使用自己的类,前提是它们实现ISerializable并具有反序列化器构造函数。我没意见。

    我和我的一个朋友谈过这一点,他主张使用只包含数据传输对象的路由,在该路由中,我必须为数据传输维护一个单独的DataContract对象图,并在客户机上重新实现我的服务器对象。

    我的另一个朋友说,因为我的服务只有两个操作(“GetServerConfiguration”和“PutServerConfiguration”),所以完全跳过WCF并实现我自己的使用套接字的服务器可能是值得的。

    所以我的问题是:

    • 以前有人遇到过类似的问题吗?如果有,有更好的方法吗?将整个对象图发送给客户机进行处理是否明智?我应该将其分解,以便客户机根据需要请求对象图的一部分,并且只发送已更改的位(从而降低与并发性相关的风险?)?
    • 如果向下发送对象图形是正确的方式,那么WCF是正确的工具吗?
    • 如果wcf是正确的,那么让wcf序列化对象图的最好方法是什么?
    2 回复  |  直到 14 年前
        1
  •  3
  •   Leon Breedt    14 年前

    对象图可以与DataContract序列化一起使用。

    注: 确保您正在保留对象引用,这样当它们都应该是同一引用时,您就不会在图形中得到同一对象的多个副本,默认行为不会像这样保留标识。

    这可以通过指定 preserveObjectReferences 构造时的参数 DataContractSerializer 或者通过指定 true 对于 IsReference 上的属性 DataContractAttribute (最后一个属性需要.NET 3.5SP1 )

    但是,在通过WCF发送对象图时,如果不注意确保图的大小保持在合理的范围内,则有可能会违反WCF配额(而且有许多配额)。

    对于 net.tcp 例如,要设置的重要传输是 maxReceivedMessageSize , maxStringContentLength maxArrayLength . 更不用说图表中允许的65335个不同对象的隐藏配额( maxObjectsInGraph ,这只能很难克服。

    您还可以使用只公开读访问器的类 DataContractSerializer ,并且没有无参数构造函数:

    using System;
    using System.IO;
    using System.Runtime.Serialization;
    
    class DataContractTest
    {
        static void Main(string[] args)
        {
          var serializer = new DataContractSerializer(typeof(NoParameterLessConstructor));
    
          var obj1 = new NoParameterLessConstructor("Name", 1);
    
          var ms = new MemoryStream();
          serializer.WriteObject(ms, obj1);
    
          ms.Seek(0, SeekOrigin.Begin);
    
          var obj2 = (NoParameterLessConstructor)serializer.ReadObject(ms);
    
          Console.WriteLine("obj2.Name: {0}", obj2.Name);
          Console.WriteLine("obj2.Version: {0}", obj2.Version);
        }
    
        [DataContract]
        class NoParameterLessConstructor
        {
            public NoParameterLessConstructor(string name, int version)
            {
              Name = name;
              Version = version;
            }
    
            [DataMember]
            public string Name { get; private set; }
            [DataMember]
            public int Version { get; private set; }
        }
    }
    

    这是因为 DataContractSerializer 无法在不调用构造函数的情况下实例化类型。

        2
  •  0
  •   marc_s HarisH Sharma    14 年前

    你把自己和序列化程序搞混了:

    • 这个 XML序列化程序 需要无参数的构造函数,因为在反序列化时,.NET运行时将实例化该类型的新对象,然后设置其属性

    • 这个 DataContractSerializer 没有这样的要求

    查看 blog post by Dan Rigsby 这就解释了序列化程序的所有荣耀,并对两者进行了比较。

    现在,对于您的设计,我的主要问题是:有一个返回所有设置的函数,客户端处理这些设置,然后另一个接收所有信息的函数,这样做有意义吗?

    你不能把这些东西分成更小的块,更小的方法调用吗?例如,是否有单独的服务方法来设置配置的每个项目?这样,你可以

    • 减少通过线路发送的数据量-要序列化和反序列化的对象图将更简单。
    • 使您的配置服务更加细化-例如,如果有人需要设置一个小属性,该客户机不需要读取整个大服务器配置,设置一个属性,并发送回大的块-只需调用适当的方法设置一个属性