は、インタフェースを変更するためのソリューションです:
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
インスタンスを作成し、そのペースを介してそれらを置く:
3/16/2012 10:43:55 AM
Hand soap
別のオプションです:実行、印刷が
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);
}
...上記を破棄して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
には、2つの汎用パラメータとIOrderItem
上の制約のない一般的なパラメータと上記の最初の提案です。私が掲示して編集した以前のバージョンは、それぞれ同じ制約を持つ同じ2つのジェネリックタイプを持つ両方のインターフェースを持っていました。私はこれが少し外に出ているように感じたので、上記の実装に戻してみました。 TOrder
型パラメータの制約が全くないにもかかわらず、IOrderItem
の型パラメータに置き換えられました。他の型の代わりにその型を変更しようとすると(たとえば、object
)、コンパイルエラーが発生しました。 T
を呼び出す代わりにTOrder
を使用すると、型制約がない場合に期待される型に関するヒントが得られます。それが私の最終編集です - 私はそれが私の試みの中で最も簡潔だと感じます。面白いと思うなら、私はインターフェイス上に二重ジェネリック制約付きの型を持っていた前の実装を提供することができますが、これは少なくとも私の好みのこの解決策です。乾杯!
[これは面白いかもしれません](http://msdn.microsoft.com/en-us/library/dd469487.aspx) – abatishchev