2012-05-30 18 views
1

我正在寫一個基於TCP連接的DLL。
基本前提是它可以被任何客戶端使用,並且所有客戶端需要做的是提供一個IP地址和一個端口號,然後dll負責連接,傳輸消息,檢測斷開連接等。 dll公開3個事件Connected,DisconnectedMessageReceived客戶端只需連接到這些使用它。 該DLL還定義了一個基類Message-類,客戶端可以繼承它們,然後將它們自己的類/對象傳遞到DLL中以進行發送/接收。在流上處理不同類的類型

在DLL我已經定義了一個Packet -class和支持類型:

[Serializable] 
internal class Packet 
{ 
    private MessageType _type; 
    private MessageItem _item; 

    public MessageType MYtpe 
    { 
     get 
     { 
      return _type; 
     } 
     set 
     { 
      _type = value; 
     } 
    } 

    //similar for MessageItem 
    // ... 
} 

枚舉:

public enum MessageType 
{ 
    None, 
    PollItem, 
    Binary1, 
    Binary2 
} 

和基類對象/類發送:

public abstract class MessageItem 
{ 
} 

我的低級別,發送類,代碼,隱藏在DLL中,然後是(沒有錯誤處理)

internal bool SendPacket(Packet p) 
{ 
    bool sentOk = false; 
    BinaryFormatter bin = new BinaryFormatter(); 
    try 
    { 
     bin.Serialize(theNetworkStream, p); 
    } 
    catch etc.. 
} 

ReadPacket基本上與此相反。

的DLL公開爲客戶端使用一個函數,構造包及以上的客戶端發送功能

public void SendMessage(MessageType type, MessageItem message) 

現在要求。 因爲我在DLL中定義了2個二進制枚舉類型,我可以在我的客戶端代碼中使用2個獨立的類。

例如

public class Employee : MessageItem 
{ 
    string name; 
    //etc 
} 

,並說:

public class Car : MessageItem 
{ 
    string Model; 
    //etc 
} 

這一切工作,我可以做接受或兩類:

if(myConnection.NextMessageType() == MessageType.Binary1) 
{ 
    Employee e = (Employee)myConnection.ReadMessage(); 
} 
if(myConnection.NextMessageType() == MessageType.Binary2) 
{ 
    Car c = (Car)myConnection.ReadMessage(); 
} 

只要客戶端始終發送Employee類型, binary1Car作爲binary2

如果我想發送第三種類型的對象/類,此刻我必須進入dll,添加一個枚舉; binary3,重建DLL,然後我可以在我的客戶端再次派生,並在上述接收代碼中使用第3個if條款。

if(myConnection.NextMessageType() == MessageType.Binary3) 
{ 
    Animal a = (Animal)myConnection.ReadMessage(); 
} 

因此,最後到我的問題!

有沒有一種方法可以避免重建DLL,但客戶端可以通過DLL發送儘可能多的不同的類類型,並且DLL中的發送/接收機制(隱藏於客戶端)仍然可以工作? 我也認爲長名單if messagetype == 1, 2 3等突出了一個糟糕的設計,但我不能確定一個更好的設計會是什麼。

如果你瞭解了這麼多,明白我在問什麼,謝謝!真的很感激解決方案。

+0

爲什麼你需要自己實現這些東西?不能爲你做連接/分配信息部分嗎?如果是這樣,而是去多種方法(例如'HandleEmployee' /'HandleCar' /'HandleAnimal'),所以你可以是類型安全 –

回答

0

最簡單的解決方案是將MessageType枚舉更改爲字符串,並完全擺脫枚舉。變化: -

public void SendMessage(MessageType type, MessageItem message) 

逼到: -

public void SendMessage(MessageItem message) 

,然後改變了sendpacket到:

internal bool SendPacket(Packet p) 
{ 
    bool sentOk = false; 
    BinaryFormatter bin = new BinaryFormatter(); 
    try 
    { 
    bin.write (p.MessageItem.GetType().Name); // or whatever the write/serialise function is called 
    bin.Serialize(theNetworkStream, p); 
    } 
    catch etc.. 
} 

然後,接收器首先讀取字符串,然後使用反射來創建一個然後以僞代碼將對象解串:

string message_type = ethernet.readstring(); 
Type item_type = convert_name_to_object_type; 
ConstructorInfo constructor = item_type.GetConstructor(); 
object item = constructor.Invoke(); 
ethernet.Deserialise (item); 
invoke MessageReceived event (item); 

最後一部分可以使用SortedDicationary <message type name, message handler delegate>將消息分派給正確的處理程序(但這會強制處理程序將MessageItem參數轉換爲正確的消息類型)。或者,再次使用反射來查找名爲「HandleEthernetMessage」的方法,該方法接收通過以太網接收的類型的一個參數。 SortedDicationary <message type name, method info>在運行時會更快並克服第一個SortedDictionary問題。

+0

這似乎可能是一個goer感謝。雖然我不確定將什麼函數用於僞代碼的convert_name_to_object_type位。 – Keith

+0

@Keith:你可以在程序集中搜索一個具有相同名稱的類型,也可以將一個預期類型的​​數組傳遞給DLL,然後搜索它。 – Skizz

+0

嗨,我不完全確定你的意思是「搜索程序集」,該DLL可以搜索調用exe的程序集?對不起,如果我有點暗淡。它只是派生類將只在exe的程序集中,而不是在dll程序集中,所以我不確定dll可以在自己的範圍之外進行搜索以便說話?也許它可以? – Keith

相關問題