2010-04-18 77 views
6

我知道標題有點混亂,但與我一起。 (我對一個新的標題大聲笑的建議) 我正在寫一個TemplateEngine,它允許我在基於文本的文件中使用我自己的標記。我想要在應用程序成熟時將插件添加爲插件。目前我有一個像這樣的結構:在實現具有對象類型屬性的接口的類中更改屬性類型

interface IControl 
    string Id 
    object Value 

class Label : IControl 
    string Id 
    string Value 

class Repeater : IControl 
    string Id 
    List<IControl> Value 

現在,您將在具有Value屬性的Repeater類中立即看到奇怪的部分。我希望在接口中使用Value類型作爲對象,可以讓我靈活地隨着我的進行擴展控件。編譯器不喜歡這個,我猜是很好的理由。底線:我試圖讓所有控件類實現相同的接口,但Value屬性的類型不同。

有沒有人有任何建議如何做到這一點?

注意:請不要使用Spark View Engine進行模板建議。有一個原因,我爲自己創造額外的工作。

+0

你在問什麼? – SLaks 2010-04-18 19:48:47

+0

@SLaks:LOL對不起,我可能需要有一個視頻剪輯解釋它好一點。試圖進入更多的細節可能會導致一個新穎的 – used2could 2010-04-18 19:51:26

+0

我試圖讓所有控件類實現相同的接口,但具有不同類型的值屬性。 – used2could 2010-04-18 19:59:51

回答

8

通常Repeater會實現一些不同的東西,例如IItemsControl

編輯1

(爲簡潔,刪除)

EDIT 2

沒關係啊,你可以隨時使用過程中的顯式接口實現:

interface IControl 
{ 
    string Id { get; set; } 
    object Value { get; set; } 
} 

class Label : IControl 
{ 
    public string Id { get; set; } 
    public string Value { get; set; } 

    object IControl.Value 
    { 
     get { return this.Value; } 
     set { this.Value = (string)value; } 
    } 
} 

class Repeater : IControl 
{ 
    public string Id { get; set; } 
    public IList<IControl> Value { get; set; } 

    object IControl.Value 
    { 
     get { return this.Value; } 
     set { this.Value = (IList<IControl>)value; } 
    } 
} 
+0

是啊,這是我能想到的唯一的其他路線 – used2could 2010-04-18 19:52:07

+0

+1瞭解我甚至在談論什麼廢話 – used2could 2010-04-18 19:53:23

+0

洛爾茲...只是訓練我的透視技能: - > ...我用一個例子更新了我的答案。 – herzmeister 2010-04-18 19:58:56

1

無,編譯器不允許相同的名稱字段是不同的t數據類型,而不是在派生類中的接口中定義的數據類型。

應該在派生類中實現屬性(因爲在接口中不允許有字段),它們需要具有相同的數據類型。所以,你不可能在沒有明確聲明的情況下用屬性來做。然而,如果你讓一個函數返回Value,那麼它可以工作,但是你需要檢查返回類型,因爲返回類型應該匹配該函數,否則你會得到錯誤,說明該接口的函數沒有實現。

interface IControl 
    { 
     object Value(); 
    } 
    class A : IControl 
    { 
     string m_value = string.Empty; 
     public object Value() { return m_value; } 
    }; 
    class B : IControl 
    { 
     List<IControl> m_value = new List<IControl>(); 
     public object Value() { return m_value; } 
    }; 
    .... 
    object o = new B().Value(); 
    if (o is List<IControl>) 
     MessageBox.Show("List"); 

[更新]
你必須要小心,如果顯式定義屬性的身體。如果不謹慎地執行實施,那麼擁有兩個屬性的名稱會很危險。

這兩個屬性如果包含不同的定義,那麼對於接口和類的最終使用將是無法解釋的。

 public IList<IControl> Value 
     object IControl.Value 

見這個例子:

... 
    class Repeater : IControl 
    { 
     List<IControl> m_Value = new List<IControl>(); 
     public IList<IControl> Value 
     { 
      get { return this.m_Value; } 
      set { this.m_Value = (IList<IControl>)value; } 
     } 
     object IControl.Value 
     { 
      get 
      { 
       return this.m_Value; 
      } 
      set 
      { 
       this.m_Value = new List<IControl>(); 
       this.m_Value.Add(new Label()); 
       this.m_Value.AddRange((List<IControl>)value); 
      } 
     } 
    } 
    ... 
    Repeater b = new Repeater(); 
    IControl i = b; 
    List<IControl> list = new List<IControl>(); 
    list.Add(new Repeater()); 
    i.Value = list; 

你可以看到,在轉發列表容器會有不同的值,當數據通過ICONTROL增加(因爲IContainer.Value的明確定義的)。

+0

+1感謝您指出明確定義屬性的擔憂。 – used2could 2010-04-19 11:10:48

3

你也可以使用泛型:

interface IControl<T> 
{ 
    string ID{get;set;} 
    T Value{get;set;} 
} 

class SomeControl : IControl<string> 
{ 
    public string ID{get;set} 
    public string Value{get;set;} 
} 

class SomeOtherControl : IControl<int> 
{ 
    public string ID{get;set} 
    public int Value{get;set;} 
} 

我喜歡這個比顯式接口想法更好,如果它是需要改變只有一個返回值。不過,我想如果你有幾個屬性,每個屬性都會返回不同的類型,那麼你不想擁有IControl。至少,我不會。在這種情況下,我會推薦顯式接口。

當然,如果您無法訪問IControl的源代碼,這將不起作用。

編輯:有一個錯字。固定

+0

是的,我們也可以使用泛型,我沒有想過它,因爲我被大多數不喜歡帶泛型類型參數的控件的UI設計工具洗腦。 ;-) – herzmeister 2010-04-18 20:17:18

+0

我想到了泛型,它被管理層拒絕了。對於那些不熟悉圖書館細節的開發者來說,這件事並不容易......(我只是收集一張支票) – used2could 2010-04-19 11:03:24