Ecco una soluzione per la modifica delle interfacce:
interface IOrder<TOrder, TOrderItem>
where TOrderItem : IOrderItem<TOrder>
{
IList<TOrderItem> Items { get; set; }
}
interface IOrderItem<TOrder>
{
TOrder Parent { get; set; }
}
apportare modifiche al StoreOrder
e StoreOrderItem
per supportare l'interfaccia cambia E aggiungendo un paio di proprietà a ciascuno per un test successivo:
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; }
}
... e ora la creazione di StoreOrder
e StoreOrderItem
casi, e metterle alla prova:
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);
}
... quando viene eseguito, stampata:
3/16/2012 10:43:55 AM
Hand soap
Un'altra opzione è per rimuovere quanto sopra e prendere this solution e modificarlo aggiungendo la proprietà Parent con il tipo desiderato e utilizzando l'implementazione dell'interfaccia esplicita per evitare il cast dei siti di chiamata, Perfetta per un qualcosa di StoreOrderItem
implementazione di simile:
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; }
}
}
Il mio preferito di quanto sopra è la prima proposta di cui sopra con i parametri di due generici a IOrder
e non vincolato generic-parametro IOrderItem
. Una versione precedente che avevo pubblicato e che ora avevo modificato aveva entrambe le interfacce con gli stessi due tipi generici ciascuno con gli stessi vincoli.Mi sono sentito come se questo fosse un po 'esagerato, quindi l'ho ridimensionato all'implementazione di cui sopra. Sebbene sia presente una completa mancanza di vincoli sul parametro di tipo TOrder
su IOrderItem
- i tentativi di fudge altri tipi al suo posto (ad es., object
) hanno provocato errori di compilazione. L'utilizzo di TOrder
invece di chiamarlo semplicemente T
fornisce un suggerimento sul tipo previsto in assenza del vincolo di tipo. Questa sarà la mia modifica finale - ritengo che sia il più succinto dei miei tentativi; se sei curioso, posso fornire la precedente implementazione che aveva i tipi double-generic-constrained sulle interfacce, ma questa è almeno la mia soluzione preferita. Saluti!
[Potrebbe essere interessante per voi] (http://msdn.microsoft.com/en-us/library/dd469487.aspx) – abatishchev