2011-04-15 22 views
0

我正在嘗試編寫一些基礎結構以方便更新服務器和客戶端之間的對象。這可能會在遊戲中使用,但是,我覺得這個問題並不完全針對遊戲(所以我在這裏問過)。網絡傳輸的高效(空間)序列化

爲了安全和效率的原因,我希望服務器有選擇地更新對象屬性。例如,對象的特定屬性可能僅對控制該對象的客戶端有用,因爲服務器只會用此信息更新「所有者」。或者,某些屬性可能需要發送給所有客戶端。爲了實現這一點,我已經定義指定的方式的自定義屬性,其中所述網絡應處理特性:

[AttributeUsage(AttributeTargets.Property)] 
    public class NetworkParameterAttribute : System.Attribute 
    { 
     public enum NetworkParameterType 
     { 
      ServerToOwner, 
      ServerToAll, 
      ServerToOwnerView, 
      OwnerToServer 
     } 

     private NetworkParameterType type; 
     public NetworkParameterType Type 
     { 
      get 
      { 
       return type; 
      } 
     } 

     public NetworkParameterAttribute(NetworkParameterType Type) 
     { 
      this.type = Type; 
     } 
    } 

現在,在一個對象類我可以定義像這樣的屬性:

public class TestObject 
    { 
     [NetworkParameter(NetworkParameterAttribute.NetworkParameterType.ServerToAll)] 
     public int ID { get; set; } 

     [NetworkParameter(NetworkParameterAttribute.NetworkParameterType.ServerToOwner)] 
     public string Name { get; set; } 
    } 

我可以然後寫一個簡單的功能,可以自動從物體抓住一組特定屬性:

public byte[] GetBytes(NetworkParameterAttribute.NetworkParameterType type) 
    { 
     MemoryStream stream = new MemoryStream(); 
     BinaryFormatter formatter = new BinaryFormatter(); 
     foreach (PropertyInfo info in this.GetType().GetProperties()) 
     { 
      foreach (object attribute in info.GetCustomAttributes(true)) 
      { 
       if (attribute is NetworkParameterAttribute && 
        ((NetworkParameterAttribute)attribute).Type == type) 
       { 
        formatter.Serialize(stream, info.GetValue(this, null)); 
       } 
      } 
     } 
     byte[] buf = new byte[stream.Length]; 
     Array.Copy(stream.GetBuffer(), buf, stream.Length); 
     return buf; 
    } 

類似的功能可以把對象返回一起在receivi方面。我遇到的問題是序列化在空間使用方面效率很低。例如,從TestObject抓取ServerToAll屬性的結果是54個字節(而它可能只有4個)。

所以問題:是否有一種更有效的方法將對象序列化爲字節流,以達到我預期的目的?請注意,我不想寫很多序列化相關的代碼。

謝謝!

回答

1

NetworkParameterAttribute應該有額外的字段,表示相應的屬性爲「髒」。對屬性的每次更改都應該有效地設置該標誌,並且在序列化期間應該重置該標誌。只有髒屬性實際上應該被序列化。

此外,現在該對象只是部分序列化,因此在序列化期間,您需要提供有關正在序列化的屬性的信息。在填充流時保持髒屬性的一個位向量,並將此位向量放入返回的字節數組的開頭。

編輯:而不是在屬性中有一個標誌,我們可以有最後序列化的實際值。好處是我們不需要爲每個屬性添加額外的代碼來保持標誌與屬性同步。在序列化期間,如果值不相等,我們會比較兩個值並序列化屬性。

+0

我喜歡這個想法,並且肯定希望將它與我已經完成的一起實施。有沒有辦法在屬性更改時自動設置該屬性? – DeusAduro 2011-04-17 18:51:17

+0

我不認爲存在這樣的機制。您需要添加代碼。但是沒有一個標誌,我們可以複製數據。我會擴大答案。 – Dialecticus 2011-04-18 13:20:42