2014-01-31 163 views
1

我正在編寫一些導入文件的代碼,這些文件將根據描述文件佈局的模板導入定界或固定寬度的文件。在接口內實現接口

我已經創建了一個接口IFileTemplate:

public interface IFileTemplate 
{ 
    string Name { get; set; } 
    bool IgnoreEmptyLines { get; set; } 
} 

其中使用由DelimitedFileTemplate類和FixedWidthFileTemplate類。

我也有確定各組成一個模板列的接口:

public interface IFileTemplateColumn 
{ 
    int ID { get; set; } 
    string Name { get; set; } 
    bool Ignore { get; set; } 
} 

這個接口,然後使用由DelimitedTemplateColumn類和FixedWidthTemplateColumn類。

由於DelimitedFileTemplate和FixedWidthFileTemplate類都將有列的列表我做了列表中IFileTemplate列中的一員:

List<IFileTemplateColumn> Fields { get; set; } 

我的問題是,當我來執行列表在DelimitedFileTemplate和FixedWidthFileTemplate類,例如:

public class FixedWidthFileTemplate : IFileTemplate 
{ 
    public int ID { get; set; } 
    public string Name { get; set; } 
    public List<FixedWidthFileTemplateColumn> Fields { get; set; } 
} 

如果我試着和List<DelimitedFileTemplateColumn>List<FixedWidthFileTemplateColumn>實現List<IFileTemplateColumn>那麼編譯器抱怨說,他們不匹配List<IFileTemplateColumn>

我可以理解這一點,但它似乎錯誤沒有在ITemplateInterface列列表。我能想到的唯一方法就是讓分隔符和固定寬度類使用List<IFileTemplateColumn>,並讓屬性getter將列表轉換爲分隔列或固定寬度列列表,但似乎有點代碼味道。任何人都可以提出一個更好的方法來做到這一點

+0

如果您爲已實現接口的類添加代碼將會更好。它會更具可讀性。 –

+0

@FaisalHafeez好的建議,現在更新。 – GrandMasterFlush

+0

我會退後一步,問爲什麼你有接口。是否有三個類實現每個接口,但除了對象之外沒有公共基類? –

回答

1

一種合適的和無臭的解決這個設計問題是泛型:

interface IFileTemplate<T> where T : IFileTemplateColumn 
{ 
    List<T> Fields { get; set; } 
} 

DelimitedFileTemplate實現IFileTemplate<DelimitedFileTemplateColumn>等。

也許文件模板之間的所有差異只能由IFileTemplateColumn明確定義,並且您可以簡化與每個FileTemplateColumn類關係中的一個FileTemplate類相關的FileTemplate<IFileTemplateColumn>

更新

至於工廠方法:IFileTemplate<IFileTemplateColumn> Create:如果此方法的消費者都應該能夠訪問列的列表,方法簽名必須包含具體ColumnTemplate。例如:

DelimitedFileTemplate Create 

interface IFactory<T> where T : IFileTemplateColumn 
{ 
    IFileTemplate<T> Create(); 
} 

class DelimitedFactory : IFactory<DelimitedFileTemplateColumn> 
{ 
    IFileTemplate<DelimitedFileTemplateColumn> Create() 
    { 
     return new DelimitedFileTemplate(); 
    } 
} 

如果該方法的消費者不會有興趣在列表中,引入更多的通用接口(很像IEnumerable<T> : IEnumerable):

interface IFileTemplate { ... } 
interface IFileTemplate<T> : IFileTemplate where T : IFileTemplateColumn 
{ 
    List<IFileTemplateColumn> Columns { get; set; } 
} 

然後你的IFileTemplate Create()方法可以返回任何具體的FileTemplate而不管該列。

我使用過這種泛型用法,它們可能會傳播(在本例中,Column層次結構將在FileTemplate層次結構中複製,並可能在工廠層次結構中複製)。有時這會顯示設計中的一些缺陷。如果你能夠明智地將IFileTemplate層次結構切割爲一個基本參數化的FileTemplate類,那肯定是一條可行的路。這就是我經常使用的方法:定義最小的部分,如果層次結構傾向於重複,那麼算法的某些部分可能會轉移到'最小部分類'。

+0

感謝您的回答,我發現在使用MVVM實施此解決方案時,您可以更輕鬆地使用第二條建議。如果列表包含不同類型的模板,則返回所有模板的列表將難以管理。 – GrandMasterFlush

+1

@GrandMasterFlush很高興你能夠自己解決這個問題。我終於有一段時間回到了這裏 - 看到更新,我有類似的問題。 – lisp

+0

感謝您的更新,這給了我更多的東西來看看。乾杯。 – GrandMasterFlush