Aquí es una solución para el cambio de las interfaces:
interface IOrder<TOrder, TOrderItem>
where TOrderItem : IOrderItem<TOrder>
{
IList<TOrderItem> Items { get; set; }
}
interface IOrderItem<TOrder>
{
TOrder Parent { get; set; }
}
Cambios a StoreOrder
y StoreOrderItem
para admitir los cambios de interfaz Y agregando un par de propiedades a cada uno para una prueba posterior:
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; }
}
... y ahora la creación de StoreOrder
y StoreOrderItem
casos, y ponerlos a prueba:
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);
}
... cuando es ejecutado, impresos
3/16/2012 10:43:55 AM
Hand soap
Otra opción es desechar lo anterior y tomar this solution y modificarlo agregando la propiedad Parent con el tipo deseado y utilizando la implementación de interfaz explícita para evitar el lanzamiento en los sitios de llamadas, haciendo para una aplicación StoreOrderItem
algo como esto:
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; }
}
}
Mi favorito de lo anterior es la primera propuesta de referencia con los parámetros de dos genéricas a IOrder
y el Libre genérica parámetros de IOrderItem
. Una versión anterior que había publicado y ahora he editado tenía ambas interfaces, cada una con los mismos dos tipos genéricos, cada una con las mismas restricciones.Sentí que esto estaba yendo un poco por la borda, así que lo reduje a la implementación anterior. Aunque hay una completa falta de limitaciones de parámetro de tipo TOrder
a IOrderItem
- intentos de eludir otros tipos en su lugar (por ejemplo, object
) dio lugar a errores de compilación. El uso de TOrder
en lugar de simplemente llamarlo T
proporciona una pista sobre el tipo esperado en ausencia de la restricción de tipo. Esa será mi edición final. Siento que es el más breve de mis intentos; si tiene curiosidad, puedo proporcionar la implementación anterior que tenía los tipos doblemente genéricos restringidos en las interfaces, pero esta es al menos mi preferida esta solución. ¡aclamaciones!
[Esto puede ser interesante para usted] (http://msdn.microsoft.com/en-us/library/dd469487.aspx) – abatishchev