C# how to set a hidden property using the "new" property?

Viewed 128

I have a class

public class MenuItem
{
    // This class have a lot of fixed properties that I can't change
    public string Foo { get; set; } 

    // Child items used to create a tree structure
    public IList<MenuItem> Items { get; set; }
}

And now I want to create a new class that inherits from MenuItem that will hold more data that I need.

public class MenuItemData<T> : MenuItem
{
    public T Data { get; set; }

    public new IList<MenuItemData<T>> Items { get; set; }
}

But to be able to have the tree structure, I need somehow to "change" the type of Items to be my new MenuItemData<T>, so I used new.

But then, the problem is that when I populate this tree structure with MenuItemData<T>, It only sets the value to the IList<MenuItemData<T>> Items and not the IList<MenuItem> Items which will be used to create the tree structure.

So I need somehow to set both Items for it to work... but I don't know how to do that.

What I tried to do is set the tree structure with the IList<MenuItemData<T>> Items and then traverse the tree and set the hidden property, but I also don't know how I can get the "new" property and set it's value to the hidden property (the "new" property inherits from the hidden property, so I should be able to set the value from one to the other).

Please notice that:

  • I cannot change the MenuItem class.
  • If there's a solution without the new, it will be ok too
  • If the question is confusing, please let me know and I can give some examples on how I'm traversing the tree.
1 Answers

You can access a hidden property with a cast to the type with hidden property :

static void SetItems<T>(MenuItemData<T> menu, IList<MenuItemData<T>> items)
{
    menu.Items = items;
    ((MenuItem)menu).Items = items.Cast<MenuItem>().ToList();
}

Also, you can use the keyword base to access hidden property from derived class. In addition, the class MenuItemDataList<T> implement IList<MenuItem> and IList<MenuItemData<T>> :

public class MenuItemData<T> : MenuItem
{
    public T Data { get; set; }
    public new IList<MenuItemData<T>> Items
    {
        get => (MenuItemDataList<T>)base.Items;
        set => base.Items = new MenuItemDataList<T>(value);
    }
}

public class MenuItemDataList<T> : List<MenuItemData<T>>, IList<MenuItem>
{
    public MenuItemDataList(IList<MenuItemData<T>> items) : base(items)
    {}

    MenuItem IList<MenuItem>.this[int index]
    {
        get => this[index];
        set => this[index] = (MenuItemData<T>)value;
    }
    bool ICollection<MenuItem>.IsReadOnly => false;
    void ICollection<MenuItem>.Add(MenuItem item) => Add((MenuItemData<T>)item);
    bool ICollection<MenuItem>.Contains(MenuItem item) => item is MenuItemData<T> data && Contains(data);
    void ICollection<MenuItem>.CopyTo(MenuItem[] array, int arrayIndex) => throw new NotImplementedException();
    IEnumerator<MenuItem> IEnumerable<MenuItem>.GetEnumerator() => GetEnumerator();
    int IList<MenuItem>.IndexOf(MenuItem item) => item is MenuItemData<T> data ? IndexOf((MenuItemData<T>)item) : -1;
    void IList<MenuItem>.Insert(int index, MenuItem item) => Insert(index, (MenuItemData<T>)item);
    bool ICollection<MenuItem>.Remove(MenuItem item) => Remove((MenuItemData<T>)item);
}
Related