Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How do I reference a parent from a child object with generic interfaces in C#?

I have the following interface declarations:

interface IOrder<T> where T: IOrderItem
{
     IList<T> Items { get; set; }
}

interface IOrderItem
{
     IOrder<IOrderItem> Parent { get; set; } // What do I put here?
}

I want the items in the list to have a reference to the header object, so it can use the ID and other fields from the header.

In my concrete classes, it complains that I don't implement "Parent" properly.

class StoreOrder : IOrder<StoreOrderItem>
{
    public IList<StoreOrderItem> Items { get; set; }
}

class StoreOrderItem : IOrderItem
{       
    public StoreOrder Parent { get; set; } // This doesn't satisfy the interface
}

I tried setting up IOrderItem as IOrderItem<T> and passing in the Parent type, but that lead to circular reference since the Header class requries the Item class type... I got confused.

Any advice on how to implement this properly?

like image 397
IronicMuffin Avatar asked Mar 15 '12 18:03

IronicMuffin


2 Answers

If you define your interfaces like so:

interface IOrder<T> where T : IOrderItem<T>
{
    IList<T> Items { get; set; }
}
interface IOrderItem<T> where T : IOrderItem<T>
{
    IOrder<T> Parent { get; set; }
}

You can then implement them like this to get the functionality that you expect:

class StoreOrder : IOrder<StoreOrderItem>
{
    public IList<StoreOrderItem> Items { get; set; }
}
class StoreOrderItem: IOrderItem<StoreOrderItem>
{
    public IOrder<StoreOrderItem> Parent { get; set; }
}
like image 188
Charles Lambert Avatar answered Sep 25 '22 17:09

Charles Lambert


class StoreOrder : IOrder<StoreOrderItem>
{
    public int Id { get; set; }
}

class StoreOrderItem : IOrderItem
{       
    public IOrder<IOrderItem> Parent { get; set; } // This doesn't satisfy the interface
}

You may not specialize - IOrder<IOrderItem> is more general than StoreOrder

like image 32
Eugen Rieck Avatar answered Sep 25 '22 17:09

Eugen Rieck