下面是接口變化的解決方案:
interface IOrder<TOrder, TOrderItem>
where TOrderItem : IOrderItem<TOrder>
{
IList<TOrderItem> Items { get; set; }
}
interface IOrderItem<TOrder>
{
TOrder Parent { get; set; }
}
進行更改StoreOrder
和StoreOrderItem
以支持接口更改和爲以後的測試添加了一些屬性:
class StoreOrder: IOrder<StoreOrder, StoreOrderItem>
{
public DateTime Date { get; set; }
public IList<StoreOrderItem> Items { get; set; }
}
class StoreOrderItem : IOrderItem<StoreOrder>
{
public string ItemName { get; set; }
public decimal ItemPrice { get; set; }
public StoreOrder Parent { get; set; }
}
...現在創建StoreOrder
和StoreOrderItem
實例,並把他們通過他們的步伐:
void Main()
{
var so = new StoreOrder { Date = DateTime.Now };
var item = new StoreOrderItem {
Parent = so,
ItemName = "Hand soap",
ItemPrice = 2.50m };
so.Items = new [] { item };
Console.WriteLine(item.Parent.Date);
Console.WriteLine(so.Items.First().ItemName);
}
...運行時,印刷:
3/16/2012 10:43:55 AM
Hand soap
另一種選擇是要取消上述並採取this solution並通過添加具有所需類型的Parent屬性並使用顯式接口實現來更改它,以避免在呼叫站點投射,鬧了StoreOrderItem
實現是這樣的:
class StoreOrderItem : IOrderItem
{
public string ItemName { get; set; }
public decimal ItemPrice { get; set; }
public StoreOrder Parent { get; set; } // note: original implementation
IOrder<IOrderItem> IOrderItem.Parent { // explicit interface implementation
get { return (IOrder<IOrderItem>)this.Parent; }
set { this.Parent = (StoreOrder)value; }
}
}
我上面的最愛是以上兩個泛型參數IOrder
和IOrderItem
不受約束的泛型參數的第一個建議。之前發佈的版本和現在編輯的版本都具有相同的兩個通用類型,每個通用類型具有相同的約束。我覺得這有點太過分了,所以我削減了上面的實現。儘管在TOrder
類型參數到IOrderItem
之間完全沒有約束 - 試圖在其位置使用其他類型(例如,object
)導致編譯錯誤。使用TOrder
而不是僅僅調用它,T
在沒有類型約束的情況下提供了有關預期類型的提示。這將是我的最終編輯 - 我覺得這是我嘗試的最簡潔的方式;如果你很好奇,我可以提供在接口上具有雙通用約束類型的前一個實現,但這至少是我最喜歡的這種解決方案。乾杯!
[這可能對你有意思](http://msdn.microsoft.com/en-us/library/dd469487.aspx) – abatishchev 2012-03-15 18:54:33