2009-12-28 78 views
2

在我的公司系統中,我們使用一個類來表示bean。它只是使用boost :: variant和一些序列化/反序列化的信息的持有者。它運行良好,但我們遇到了一個問題:它不在接口之上,並且由於我們通過dll使用模塊化,爲它構建接口變得非常複雜,因爲它幾乎被應用程序的每個部分所使用,並且可悲地接口(抽象類)必須通過指針訪問,巫婆幾乎不可能重構整個系統。Turn class「Interfaceable」

我們的結構是:

DLL答:通過抽象類
DLL接口B定義:接口實現

有一種無痛的方式來實現這一目標(可能使用模板,我不知道)或者我應該忘記做這個工作,並簡單地鏈接所有與DLL B?

謝謝

編輯:這是我的例子。
這是在dll上A
BeanProtocol是N dataprotocol itens的持有者,它由索引處理。

class DataProtocol; 

class UTILS_EXPORT BeanProtocol 
{ 
public: 
    virtual DataProtocol& get(const unsigned int ) const 
    { 
    throw std::runtime_error("Not implemented"); 
    } 

    virtual void getFields(std::list<unsigned int>&) const 
    { 
    throw std::runtime_error("Not implemented"); 
    } 

    virtual DataProtocol& operator[](const unsigned int) 
    { 
    throw std::runtime_error("Not implemented"); 
    } 

    virtual DataProtocol& operator[](const unsigned int) const 
    { 
    throw std::runtime_error("Not implemented"); 
    } 

    virtual void fromString(const std::string&) 
    { 
    throw std::runtime_error("Not implemented"); 
    } 

    virtual std::string toString() const 
    { 
    throw std::runtime_error("Not implemented"); 
    } 

    virtual void fromBinary(const std::string&) 
    { 
    throw std::runtime_error("Not implemented"); 
    } 

    virtual std::string toBinary() const 
    { 
    throw std::runtime_error("Not implemented"); 
    } 

    virtual BeanProtocol& operator=(const BeanProtocol&) 
    { 
    throw std::runtime_error("Not implemented"); 
    } 

    virtual bool operator==(const BeanProtocol&) const 
    { 
    throw std::runtime_error("Not implemented"); 
    } 

    virtual bool operator!=(const BeanProtocol&) const 
    { 
    throw std::runtime_error("Not implemented"); 
    } 

    virtual bool operator==(const char*) const 
    { 
    throw std::runtime_error("Not implemented"); 
    } 

    virtual bool hasKey(unsigned int field) const 
    { 
    throw std::runtime_error("Not implemented"); 
    } 
}; 

其他類(名爲GenericBean)實現它。這是我發現這個工作的唯一方法,但是現在我想將它轉換爲一個真正的接口並刪除UTILS_EXPORT(這是一個_declspec宏),最後刪除B與A的強制關聯。

+0

你可以添加一些示例代碼?真的很難判斷你的問題到底是什麼。 – 2009-12-28 16:23:21

+0

我不明白,一個抽象類的DLL?沒有代碼。 – 2009-12-28 16:30:53

+0

爲什麼使用異常而不是純虛擬方法? – 2010-01-06 05:20:28

回答

0

DLL答:通過抽象類的接口定義

DLL B:接口實現

你能解釋一下你的接口implementaion是什麼意思?在理想的情況下,接口應該不過是簡單的標題。即使你有一些默認的實現,鏈接它們是否有很大的負擔?

您所描述的實質上是一種插件體系結構。恐怕有沒有乾淨的方式通過DLL來做到這一點。

當然,如果你只在Windows上,你可以創建COM類(簡單)或查找__declexport關鍵字。

是的,使用dll時,我會遠離模板 - 它們通常會造成比它們更大的麻煩。

+0

-1,錯了。 DLL A將創建一個vptr表,DLL B將創建第二個vptr表,並且這些類將不兼容。 – Joshua 2009-12-28 16:37:29

+0

@Joshua:我不確定你指的是我的帖子的哪一部分。 – dirkgently 2009-12-28 16:41:31

+0

由於DLL的工作方式,關於「mere headers」的部分會導致vtable問題。 – Joshua 2009-12-28 17:44:17

0

如果我記得你必須在DLL A中實現第一個列出的構造函數,並用.DEF文件中的exports表導出該構造函數和VTABLE。

0

老實說,我真的不明白你在做什麼,看起來你對「界面」有不同的理解,因爲你使用DLL來「存儲」基礎(界面/核心/等等)和你所謂的「接口」有「實現」!如果你現有的解決方案沒有圍繞接口構建,那麼如果你引入它們,它將需要重新編譯,很可能沒有從管理的角度去看待(除非你的經理也是技術怪傑)。

0

看,我可能完全不在這裏,因爲我在理解你的問題時有點麻煩。但是,如果我是正確的,您想要刪除A和B之間的強制關聯。

您有接口類,它具有所有純虛擬方法。您的應用程序使用此類型的指針與具體對象進行通信。

您的DLL實現了抽象類,保持DLL中的所有內存分配和銷燬。

您在DLL中創建了一個工廠函數,它返回一個抽象類型的指針,但它是否實際實例化了一個具體對象。工廠函數需要導出到DLL中,沒有別的。

現在,您可以在運行時鏈接到dll,調用工廠函數並實例化對象。

難道你喜歡什麼?

+0

這是我想要做的,但問題只是在我的系統上我沒有作爲指針訪問它(因爲它們不是純虛擬的),我無法做到這一點,因爲重構將是瘋狂的。 – scooterman 2010-03-19 14:32:06

1

我不完全確定你的意思,但如果問題是BeanProtocol不是一個指針,那麼你不能讓它包裝一個指向另一個類的指針(比如BeanPointerImpl),然後你可以從你的DLL。

class BeanProtocol 
{ 
    private BeanProtocolImpl m_impl; 
    public: 
    DataProtocol& get(const unsigned int index) const 
    { 
    if(! m_impl) 
    { 
     load_impl(get_appropriate_dll()) 
    } 
    return m_impl->get(index); 
    } 

...等等BeanProtocol上的所有其他方法。

然後你可以實現你的插件BeanProtocolImpl爲不同的子類,從您的DLL(DLL中的B這種情況下)導出它們和廢料DLL A.

在這個例子中,我假設load_impl負荷DLL,調用工廠方法來獲取BeanProtocolImpl的實現並將其存儲在m_impl中,如果加載失敗則拋出異常。

當然,您需要重新編譯整個應用程序,但不能重構它。