我有一个服务端专门来接收数据, 从客户端传来的json字符串经过反序列化得到一个对象,但是因为这个对象里的一条属性有可能是任意类型的,服务器这边无法判断,所以我用了一个object来接收这条属性。消息对象如下:namespace WindowsFormsSocketChat
{
    //本类为收到的消息对象结构
    [DataContract]
    [KnownType(typeof(ObjectMessage))]
    [KnownType(typeof(ListMessage))]
    [KnownType(typeof(StringMessage))]
    public class Message
    {        [DataMember(Order=0)]//[IgnoreDataMember] 不序列化此字段加此标签      
        public int MessageType  { get; set; } //消息类型        [DataMember(Order = 1)]
        public string sessionID { get; set; } //用户会话id        [DataMember(Order = 2)]
        public string MessageFrom { get; set; } //消息发出者        [DataMember(Order = 3)]
        public List<string> MeseageTo = new List<string>(); //消息分发的用户名列表        [DataMember(Order = 5)]
        public string time = DateTime.Now.ToString();//消息发出时间    }    //本类为发出的消息对象结构
    [DataContract]
    public class ObjectMessage : Message
    {        [DataMember(Order = 4)]
        public object obj{get;set;}//消息分发的用户名列表    }    //本类为发出的消息对象结构
    [DataContract]
    public class ListMessage : Message
    {        [DataMember(Order = 4)]
        public List<UserInfo> obj { get; set; } //消息分发的用户名列表    }    //本类为发出的消息对象结构
    [DataContract]
    public class StringMessage : Message
    {        [DataMember(Order = 4)]
        public string obj { get; set; } //消息分发的用户名列表    }
}现在的问题是,当客户端传来的message对象里的obj属性是一个对象的集合时,服务端ObjectMessage接收的数据返回的obj属性是个object[]类型,而且里边为空。这要怎么办呢?怎样用一个公共的消息对象来接收不同类型的消息

解决方案 »

  1.   

    基本上是这样的。你可以首先定义一个用来通讯的基本包装public class Packet
    {
      public string TypeFullName;
      public string JsonObjectSerialization;
    }可能我删除了两三个你不需要的字段。但是这说明了,服务器要反序列化的类型名称,以及json串。这个对象(类)时可以直接序列化,并传给服务器的。服务器反序列化出Packet类型的对象,然后再反序列化出它所承载的真实对象。
      

  2.   


    你的意思我明白,这个办法其实还可以通过我直接 用正则来判断MessageType后边的值,然后来用不同的消息对象来接收,但是这样存在一个问题。我的接收方法是写在一个核心类里的,也就是说,这个框架类要与业务逻辑分离开,按照上边你的办法,那就是要在消息压入消息队列之前来做一个2次反序列化的方法,里边包含选择用哪一种消息对象来接收。但是问题是。
    我这个MessageType是准备用来给用户自由定义的,他的类型是用户来指定,那么回不回把业务逻辑也给参合到底层类里了?
      

  3.   

    正则?晕。不得已、实在没有办法时才用正则。参合什么业务逻辑代码呢?反射的意思恰恰就是不参合。如果你依赖于业务逻辑代码,何必还反射呢?如果你认为一个类它可以反射出业务逻辑类型的对象就是参合业务逻辑了,那么可能你还真的没有了解分层的意思。一个通讯层不是不返回业务逻辑的对象,而是它作为普通的object来返回这些对象,并不管它干什么用的。
      

  4.   

    这是一个很简单的概念问题,或者说是心理问题。心理问题有时候会让人看不懂简单的框架代码。一个业务系统的通讯网关并不是不反射各种对象,而是只作为object来处理,仅此而已。
      

  5.   

    我进一步说一点吧,比如说服务器的业务处理系统,每当通讯网关给它一个object之后,它可能首先判断这个对象有没有 ICommand 接口,如果有,救执行object result=((ICommand)obj).Execute();就行了,然后把返回的对象result再通过通讯网关序列化并返回客户端。这时候也不设计各种(可能三三百个)业务命令。再进一步说,也许命令处理系统在上面这个处理之前首先看看这个object有没有 ICacheable 接口(判断obj as ICacheable的结果是否不是null),如果有就使用请求信息json串作为key,来从高速缓存中直接拿出结果result直接返回,没有才继续调用ICommand处理(处理后放入缓存)。这样对于来自相同或者不同客户端的完全一样的请求,只要缓存没有自动清理,就可以自动使用数据缓存来输出。总之这些都跟你说的“参合业务逻辑”相关,但是这些都是跟业务逻辑分层的。这些代码都没有涉及具体的业务逻辑类型,但是无时无刻不是在处理业务命令。设计本来就是这样。你编写一个通讯程序不就是为了处理业务逻辑吗。不能光是想着实现一点技术,从(你说的)最底层通讯网关它就已经返回业务数据了,只不过从代码上看上去只是依赖高层次的接口抽象的而已。
      

  6.   


    你那个封装pack的办法确实是个非常不错的办法,你说的对,用正则那就有点违反面象对象的编程了,属于偷机取巧的办法。实在不好意思我只有25分了,你的办法解决了我很大的关键问题,我还有百度知道的分,比较多哈哈,想要的话给你点。我看了你第3贴,虽然没太看懂你所说的icommand接口的意思,因为我是初学者,但是我的理解,你所说的通信类,只是给业务逻辑返回一个object,然后由业务逻辑来判断object里的类型,来选择是否取json字符串。因为是通信所以我感觉这个obj不用写成接口的实现类,而只是写成你上边的字符串来判断类型就可以了,不知对不对。其实我原打算就是想以这个核心类为基础,再做一个封装类,里边包含各种提供给用户来使用的对象和最直接的方法。我上边说的并不准确,应该是我是不想把一些不必要的对象或方法暴露给用户。通信类传给业务逻辑的是一个消息,我的设想,就是每一种客户端的动作,都是一个命令,但是这个命令属性跟消息对象的对象类型是否应该是一个呢?
      

  7.   

    今天我按照这个办法想了想,发现个问题,如果在压队列之前就已经区分开对象的话,那怎么压入队列呢?队列要求的是同一种对象,我的想法是,要么用一个泛形类,判断类型后,根据这个类型来实力化该类
    要么就是用接口,就是一个类里的obj属性是一个实现了接口的类对象。大神给看看怎么做好点,我个人感觉泛型类更好点,因为有变化的是对象而不是方法