none
IFormatterConverter.Convert RRS feed

  • 問題

  • 請教各位,這個該如何使用,由於msdn的解釋非常的少
     Convert(object value, TypeCode typeCode)
    小弟想做的是 不管使用者 丟什麼class或struct  進去
    取得gettype之後,直將object轉型為 指定型別
    再回傳object回去
    2009年4月3日 上午 06:02

解答

  • HI,

    這種功能好像要到C# 4.0才有, 請參考:C# 4.0 goes dynamic
    4.0版以前可以參考以下的做法:http://forum.csharp-online.net/viewtopic.php?p=885&sid=e8a1a8175255ad463d1590e6401d5d37
    • 已標示為解答 ericstone 2009年4月8日 上午 03:28
    2009年4月7日 上午 03:42
  • 如果要隨意的字串,又不想變動結構,就用字串慢慢去分解吧.
    • 已標示為解答 ericstone 2009年4月8日 上午 03:28
    2009年4月7日 上午 04:01
  • 如果接收與發送端都是.Net,你可以做一個Interface或abstract class
    譬如
    interface ISocketMessage 
    {
    string GetMessageData();
    void SetMessageData(string data);
    int GetMessageType();
    }

    然後將你的每個訊息都實作此interface,處理GetMessageData與SetMessageData,並可序列化
    譬如
    [Serializeable]
    class MyMessage1 : ISocketMessage 
    {
    ....
    }

    [Serializeable]
    class MyMessage2 : ISocketMessage 
    {
    ....
    }


    而接收與發送程式用ISocketMessage  作序列化傳送.

    譬如
    //Send
    public void Send(ISocketMessage  message)
    {
    Socket socket ....
    byte[] sendData = ... //序列化ISocketMessage 
    socket.Send( sendData ...);
    }
    呼叫
    MyMessage1 message = new MyMessage1();
    Send(message);


    //Received
    ISocketMessage  Received()
    {
    byte[] sendData = ....
    return ...//反序列化ISocketMessage 
    }
    使用端
    IScoketMessage  message = Received();
    switch(message.GetMessageType())
    {
    case 1:
    MyMessage1 m1 = (MyMessage1)message;
    ....
    break;
    case 2:
    MyMessage1 m2 = (MyMessage1)message;
    ....
    break;
    }


    這些東西其實跟技術無關全都式物件導向的技巧.
    • 已標示為解答 ericstone 2009年4月8日 上午 03:28
    2009年4月7日 上午 04:36

所有回覆

  • HI,

    在.NET中, 任何型態都可以轉型成object型態, 不需要任何處理
    2009年4月6日 上午 02:25
  • sturct abc
    {
    //header
    public string id;
    public string datetime;
    //data
    public string Path
    ....
    ....
    }
    以上會有header 相同,data方面不同的多個結構

    可能小弟的問題寫不太清楚,我想寫一個function(object tmp),任何結構丟進來,
    可以直接轉化本身的型別,取值出來組合,在return回去,會想這樣是因為結構滿多的,而且如果以後需要增加的話
    只需要依照規範設計結構就行了 不需要更動程式碼,這幾天找資料時,找到 Reflection(中譯反射?) ,不過有遇到一些不太懂的地方,如果各位懂的話 希望能詳細解釋如何使用,
    如下
    getproperty時下面id是讀不到的,而datetime可以讀到,想請問這是為什麼?
    sturct abc
    {
    public string id;

    public string datetime
    {
    get{ ......}
    set{.......}
    }
    }
    2009年4月6日 上午 02:53
  • HI,

    getproperty讀不到id, 是因為id不是Property, 如果用GetMembers, 就應該可以抓到id
    2009年4月6日 上午 03:00
  • 搞了半天,看不懂你出現的問題?
    我一直在思考,有了object 和 Type 了,你怎麼還不會轉!
    你把結構改成 Class 後,就可以在IFormatterConverter.Convert 寫轉換的邏輯了.
    2009年4月6日 上午 03:44
  • 我想請問可以動態增加指定class的property or member嗎?
    2009年4月6日 上午 08:45
  • 舉個實際的例子吧!(把你的需求提出來).
    不是成示範例那一種.

    2009年4月6日 上午 10:26
  • 恩,抱歉問題寫得不清楚。
    我的需求是程式與遠端的傳遞訊息(原本打算傳xml檔),因為不考慮存取資料庫,
    但是這樣需更動socket接收部份的程式碼(原本收字串),所以想試試有沒有別的方法
    若改為訊息結構(會組成字串傳遞),那必須針對不同事件訂出結構,訊息如上述結構那樣,日後可能還會增加,如果增加的話,
    接收到時需要判斷那個結構,訊息愈多元化,判斷式就愈長,所以想寫一個common的,不管結構是什麼,只要符合規定都能拆解,小弟想到
    1.物件序列化xml字串傳遞, 接收時反序列化
    (同樣要判斷type,才能反序列化)
    自訂反序列化,將member property 動態增加到指定class or struct?    
    2009年4月7日 上午 01:45
  • HI,

    這種功能好像要到C# 4.0才有, 請參考:C# 4.0 goes dynamic
    4.0版以前可以參考以下的做法:http://forum.csharp-online.net/viewtopic.php?p=885&sid=e8a1a8175255ad463d1590e6401d5d37
    • 已標示為解答 ericstone 2009年4月8日 上午 03:28
    2009年4月7日 上午 03:42
  • 如果要隨意的字串,又不想變動結構,就用字串慢慢去分解吧.
    • 已標示為解答 ericstone 2009年4月8日 上午 03:28
    2009年4月7日 上午 04:01
  • 如果接收與發送端都是.Net,你可以做一個Interface或abstract class
    譬如
    interface ISocketMessage 
    {
    string GetMessageData();
    void SetMessageData(string data);
    int GetMessageType();
    }

    然後將你的每個訊息都實作此interface,處理GetMessageData與SetMessageData,並可序列化
    譬如
    [Serializeable]
    class MyMessage1 : ISocketMessage 
    {
    ....
    }

    [Serializeable]
    class MyMessage2 : ISocketMessage 
    {
    ....
    }


    而接收與發送程式用ISocketMessage  作序列化傳送.

    譬如
    //Send
    public void Send(ISocketMessage  message)
    {
    Socket socket ....
    byte[] sendData = ... //序列化ISocketMessage 
    socket.Send( sendData ...);
    }
    呼叫
    MyMessage1 message = new MyMessage1();
    Send(message);


    //Received
    ISocketMessage  Received()
    {
    byte[] sendData = ....
    return ...//反序列化ISocketMessage 
    }
    使用端
    IScoketMessage  message = Received();
    switch(message.GetMessageType())
    {
    case 1:
    MyMessage1 m1 = (MyMessage1)message;
    ....
    break;
    case 2:
    MyMessage1 m2 = (MyMessage1)message;
    ....
    break;
    }


    這些東西其實跟技術無關全都式物件導向的技巧.
    • 已標示為解答 ericstone 2009年4月8日 上午 03:28
    2009年4月7日 上午 04:36

  • ISocketMessage  Received()
    {
    byte[] sendData = ....
    return ...//反序列化ISocketMessage 
    }

    我想問這段如何反序列化回去呢? 反序列化不是需要來源的type嗎?
     public TrxMessage Receive(string InData)
            {
                XmlDocument xdoc = new XmlDocument();
                xdoc.LoadXml(InData);
                XmlNodeReader Reader = new XmlNodeReader(xdoc.DocumentElement);
                XmlSerializer ser = new XmlSerializer(typeof(TrxMessage));
                TrxMessage obj = ser.Deserialize(Reader) as TrxMessage;
                這行會出錯,elelment不符合
                return obj;
            }
    2009年4月7日 上午 09:20
  • 因為衍生的類別都以實做Serializable所以可以使用通用的序列化與反序列化Library即可.不需要原來型態.
    請參考相關文章,不難做到.
    其實序列化底層也就是Interface,說明白點就是物件導向設計中的多型,試想由使用者自訂的.Net Class為何都能實作序列化,.Net的Framework本身就是一個物件導向的設計模式.

    你的問題其實出在對於繼承跟Interface實作的不熟悉,你可以研讀這部分會發現其實很多彈性的東西再物件導向中都是這樣實作出來的.
    這也是物件導向為何是一些大系統必須採用的設計模式的根本原因.
    2009年4月7日 上午 09:28
  • 恩,那相關文章尋找的關鍵字 是通用序列化?
    2009年4月7日 上午 09:48
  • 參考這篇文章
    http://www.dotblogs.com.tw/puma/archive/2009/04/02/cshape-socket-class-struct-deserialize-serialize.aspx


    他用的是BinaryFormatter(因為Socket通訊底層是用Byte[]),其中BinaryFormatter.Serialize() 方法中的傳入物件型態為object,也就是任意資料型態,嚴格說是有實作序列化的物件,
    所以可以用物件導向的設計模式,將Message類別做一個底層的基底類別或Inteface,如同上面的範例.

    另外這種方式應用的範圍很廣.
    像我有隻程式底層是用MSMQ也是類似做法.
    提供你做參考

        interface IAnalyzeLog
        {
            List<IAnalyzeStrategy> GetStrategies();
        }
    
        [Serializable()]
        class ComponentOutdateAnalyzeLog : IAnalyzeLog
        {
            #region Variables
    
            ........
      
            #endregion
    
            #region Constructors
    
            public ComponentOutdateAnalyzeLog(
                ...
                )
            {
                ...
            }
    
            #endregion
    
            #region IAnalyzeLog Members
    
            public List<IAnalyzeStrategy> GetStrategies()
            {
                List<IAnalyzeStrategy> list = new List<IAnalyzeStrategy>();
    
                ...
    
                return list;
            }
    
            #endregion
     }

     

    private void AddToMQ(IAnalyzeLog log)
    {
    ...
                    BinaryFormatter bf = new BinaryFormatter();   
                    MemoryStream stream = new MemoryStream();  
                    bf.Serialize(stream, log);  
    ...
    }
    2009年4月8日 上午 01:12
  •    [XmlInclude(typeof(Command))]
        public abstract class TrxMessage
        {
            #region TrxHeader 成員
            public string name;
            public string id;
            #endregion
        }

    謝謝你的幫忙,後來我看msdn有關序列化的文件,使用了xmlinclude 這個
    使得TrxMessage的衍生類別可以反序列化,這也算是一種方法嗎?
    2009年4月8日 上午 01:30
  • 這個標籤我沒用過,但如果也是用在序列化,那應該是序列化成XML formate的一種簡易方式.
    但這樣做對於sokcet傳遞其實不是很適當,因為你還是必須將xml document轉成byte[]反而多了一道手續.
    序列化與你要通用化的問題其實沒有關聯,通用化是物件導向的設計模式,而序列化只是傳資料的一種模式,因為這非常常用所以.Net將其內建一些運作機制中.

    你可以不用.Net序列化而自己撰寫將物件轉譯成byte[].

    譬如
    inteface IMessage
    {
    byte[] GetMessageBytes();
    }


    class MyMessage : IMessage
    {
    public byte[] GetMessageBytes()
    {
    ..負責將MyMessage 必要資料轉成byte[]
    }
    }


    class MyMessage2 : IMessage
    {
    public byte[] GetMessageBytes()
    {
    ..負責將MyMessage2 必要資料轉成byte[]
    }
    }

    ...如上

    而socket部分

    private void Send(IMessage message)
    {

    socket.Send(message.GetMessageBytes()); //這邊就不需要管原來型態為何了,用多型存取各實作GetMessageBytes方法的 class,如上面的MyMessage,MyMessage2 
    ...
    }


    2009年4月8日 上午 01:40
  • 恩,使用標籤的話,當衍生類別增加時,就要在抽象類別上加入標籤,如果忘記了就錯誤了
    BinaryFormatter 的話就不用那麼麻煩了, 謝謝你的指導讓我學習了很多,
    一開始就有建立抽象類別了,不知道序列化有分那麼多種,實際去看msdn的說明才知道
    且socket的傳送是以byte,還要將資料轉成byte,
    話說你之前推薦我看的敏捷,它己經絕版了說……
    2009年4月8日 上午 03:25
  • 這本書真得是本好書,可惜國內高階書籍市場太小了.
    就像古早以前有本"世紀末軟體革命"這本國內應該說是最好的物件導向入門書,後來多年後有重新發行再版.
    這類書籍其實如同教科書,並不會隨著時間跟技術的演進而變得沒有價值,其實買這類書籍的價值遠大於其他技術書籍.
    像人月神話這本著作,作者提到的問題,現在隨著近代軟體越來越龐大慢慢都浮現出來.以往這類問題只有一些在金字塔頂端的技術人員會遇到,未來這個趨勢會慢慢向金字塔底端移動,
    在目前的情況下,未來進入程式設計的門檻只會越來越高(因為經驗),而未來很多新手大概都只能淪落到所謂的程式打字員或工具使用者.
    很明顯的未來軟體時程開發會越來越緩慢,這些狀況可以看目前一些大軟體版本更新週期越來越長,並不是工具或技術沒有增進,而是需求越來越大,要解決的不單單只是技術問題,架構整合與測試才是花時間的地方.
    2009年4月8日 上午 09:51
  • 我想問用了binary的話 要如何判斷資料的頭尾碼呢?
    2009年4月9日 上午 07:32
  • 序列化是一個有機制的架構,所以如果需要有特別需求不應該直接解析內容
    你的目的是?
    2009年4月10日 上午 12:05
  • 因為socket傳送時,過於密集時,會一次全部收進來,所以會加識別字元,以區別資料
    不過這已經解決了,謝謝你的建議提供

    2009年4月10日 上午 05:14