2017-09-15 92 views
0

將正在使用泛型的基類轉換回其派生類型的正確方法是什麼?將通用基礎對象轉換爲派生類型

我有以下對象實現。

注意,「保存」方法調用「WriteSettings」的方法在這裏(需要在BaseSettings對象)

public class Settings1 
{ 
    public string strData; 
} 

public class BaseSettings<T> 
{ 
    T settings; 
    public iSettingsDestination Destination; 

    public bool Save() 
    { 
     return Destination.WriteSettings(this); 
    } 
} 

public class Settings1Manager : BaseSettings<Settings1> 
{ 
    public bool DoSomething() 
    { 
     return true; 
    } 
} 

我已經創建了一個接口iSettingsDestination,將永遠使用基類(BaseSettings)至傳遞對象。從iSettingsDestination派生的類可以選擇要處理的對象類型。 我希望能夠將此對象作爲基本類型傳遞給方法,確定派生類型並反轉投射。 (請參閱下文)嘗試轉回派生類型時收到編譯錯誤。

public interface iSettingsDestination 
{ 
    bool WriteSettings<T>(BaseSettings<T> settings); 
} 

public class FileDestination : iSettingsDestination 
{ 
    bool WriteSettings1ManagerToFile(Settings1Manager settings) 
    { 
     // write to file 
     return true; 
    } 

    bool WriteSettings<T>(BaseSettings<T> settings) 
    { 
     if (typeof(Settings1Manager).IsAssignableFrom(settings.GetType())) 
     { 
      // generates error 
      // Cannot convert type 'BaseSettings<T>' to 'Settings1Manager' 
      return WriteSettings1ManagerToNetwork((Settings1Manager)settings); 
     } 

     // unhandled object type 
     return false; 
    } 

} 

我希望能夠調用下面的代碼。對於這裏的示例,我只顯示1種「目的地」和「設置」類型,但您可以想象這裏可以使用許多不同的類型。

void main() 
    { 
     Settings1Manager settings1 = new Settings1Manager(); 
     settings1.Destination = new FileDestination(); 
     settings1.Save(); // saves to a file 
    } 

我能夠做到這一點與其他基類,但似乎在這裏使用泛型導致問題。

1)如何在調用WriteSettings1ManagerToNetwork((Settings1Manager)設置)中正確地將其轉換回派生類型;

2)有沒有人看到任何問題公然濫用泛型/接口/等邏輯在這裏?

在此先感謝您的幫助。

回答

3

聲明爲BaseSettings<T>的引用指的是Settings1Manager的實際實例。這就是繼承的工作原理。事實上,你正在做的是鑄造一個基本類型的引用,它實際上是指你剛纔確認的對象是派生類型的

settings as Settings1Manager會編譯,因爲如果轉換失敗,as將返回null。你和我都知道特定的演員陣容不會失敗,但編劇只是遵循其規則。

if (typeof(Settings1Manager).IsAssignableFrom(settings.GetType())) 
{ 
    return WriteSettings1ManagerToNetwork(settings as Settings1Manager); 
} 

這工作太,因爲你可以投什麼object,你可以投object任何東西。但是你不希望人們在看起來像這樣的代碼上看到你的名字。

return WriteSettings1ManagerToFile((Settings1Manager)(object)settings); 
+1

太棒了!謝謝埃德! –

相關問題