2017-10-18 59 views
0

所以我有一個工作的解決方案,但我只是不確定我是否過於複雜。如何定義一個接口,以確保它的孩子和父母是與定義的接口相同的類型

假設我們有以下兩個接口:

public interface IPrototype 
{ 
    Guid Id { get; set; } 
    string Name { get; set; } 
} 

public interface IHierarchicalPrototype : IPrototype 
{ 
    IHierarchicalPrototype Parent { get; set; } 
    IList<IHierarchicalPrototype> Children { get; set; } 
} 

現在假設許多實現的IHierarchicalPrototype存在,例如IEntityPrototypeIFieldPrototype

在上述定義中的Parent可以是任何IHierarchicalPrototypeIEntityPrototypeChildren列表可以包含任何IHierarchicalPrototype

我想確定的是,IHierarchicalPrototype只能包含自己類型的孩子。因此,IEntityPrototypeChildren的類型爲IList<IEntityPrototype>,而Parent的類型爲IEntityPrototype

一個解決方案是實現爲每個從IHierarchicalPrototype派生原型ChildrenParent但有如此一個簡單的方法!

我想出的是一個有泛型的解決方案。

而不是定義

interface IEntityPrototype : IHierarchicalPrototype {} 

我可以用這樣的泛型定義它的:

interface IEntityPrototype : IHierarchicalPrototype<IEntityPrototype> 

我不能讓雖然擺脫多餘的泛型類型參數的。我想泛型類型參數總是匹配我目前定義界面,實際上只需要上述如果我想搭配的原型是這樣(我不)

// this will never happen! 
interface IEntityPrototype : IHierarchicalPrototype<IFieldPrototype> 

這裏也是一般定義的IHierarchicalPrototype接口

public interface IHierarchicalPrototype<THierarchical> : IPrototype 
    where THierarchical : IHierarchicalPrototype<THierarchical> 
{ 
    IHierarchicalPrototype<THierarchical> Parent { get; } 
    IList<IHierarchicalPrototype<THierarchical>> Children { get; } 
} 

您可以想出任何替代或更優雅的解決方案?

+2

您可能需要閱讀埃裏克利珀的[奇妙而又奇妙(HTTPS://blogs.msdn.microso ft.com/ericlippert/2011/02/03/curiouser-and-curiouser/),它討論了「奇怪的循環模板模式」,以及它爲什麼不能在C#中使用它。 –

+0

@Damien_The_Unbeliever哇,那*非常*快。非常感謝,我不知道我所實施的實際上是一種模式。非常有見地。我的確在問自己,我的實施在未來的好處是否會超過它的缺點。雖然我看不出這種模式的全部垮臺,但我現在可以理解爲什麼。如果你寫出更徹底的答案,我會很樂意接受它。 –

+0

有些事情你不能執行.... –

回答

0

感謝@Damien_The_Unbeliever我現在知道什麼我已實施實際上是一個名爲couriously recurring template pattern(CRTP)模式。

Eric LippertZp Bappi這兩個人寫了關於此更多的人誰感興趣。

[I] n的練習使用這種模式確實務實解決是很難的C#,否則建模方法的問題時,有次。[...]原因之一,人們爲什麼要做到這一點,是執行類型層次結構中的特定約束。

這個確切的原因是我試圖用我的代碼實現的。

我對Lippert的帖子也提到了對CRTP的懷疑。他建議

你實現這種奇怪的模式 在C#之前覺得很辛苦

  1. ,因爲它實際上並沒有強制約束,你認爲它
  2. 這很簡單,因爲它烤人誰讀碼
的麪條
0

如果我明白你的要求,那麼這可能會有所幫助。

public interface IPrototype 
{ 
    Guid Id { get; set; } 
    string Name{ get; set; } 
} 

public interface IHierarchicalPrototype<T> : IPrototype where T:IPrototype 
{ 
    T Parent{ get; } 
    IList<T> Children { get; } 
} 
+0

這是不正確的。 'IEntityPrototype接口:IHierarchicalPrototype '可以將'IPrototype'的任何孩子添加到它的'Children'中。但我希望它的孩子完全是「IEntityPrototype」類型的。 –

相關問題