Вот решение для изменения интерфейсов:
interface IOrder<TOrder, TOrderItem>
where TOrderItem : IOrderItem<TOrder>
{
IList<TOrderItem> Items { get; set; }
}
interface IOrderItem<TOrder>
{
TOrder Parent { get; set; }
}
Внесение изменений в StoreOrder
и StoreOrderItem
для поддержки изменений интерфейса AND добавление пары свойств к каждому дляболее поздний тест:
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
Другой вариант - отказаться от вышеупомянутого и взять это решение и изменить его, добавив свойство Parent с нужным типом и используя явную реализацию интерфейса, чтобы избежать приведения к вызову при вызове.-sites, что делает для реализации 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
дает подсказку об ожидаемом типе в отсутствие ограничения типа.Это будет мое последнее редактирование - я чувствую, что это самая краткая из моих попыток;если вам интересно, я могу предоставить предыдущую реализацию, которая имела двойные общие ограничения типа на интерфейсах, но это, по крайней мере, мое предпочтительное решение.ура!