The direction where you are going is great. I would make a few tweaks to this design like so:
public abstract class Container : Item
{
private float _MaxWeight;
private List<Item> _Items;
public List<Item> Items { get { return _Items; } }
public float MaxWeight { get { return _MaxWeight; } set { _MaxWeight = value; } }
public abstract ContainerType ContainerType { get; }
public IEnumerable<IDepositFilter> Filters { get; set; } // Probably a factory can stuff filters as required per each type.
public void DepositItem(Item item) {
foreach(var filter in Filters) {
if(!filter.IsAllowed(item)) {
throw new ItemNotAllowedException();
}
}
_Items.Add(item);
}
}
public interface IDepositFilter
{
bool IsAllowed(Item item);
}
public class DefaultContainerFilter : IDepositFilter {
// probably do nothing here
}
public class OversizeContainerFilter : IDepositFilter
{
// Check if the size of the new deposit is larger than leftover space in this container
}
public class ItemTypeFilter : IDepositFilter
{
// check what is being deposited and allow/disallow accordingly.
}
Notice, I introduced a filter collection that should be used when you are adding something to your container. You can add as many filters as you want to your container of a specific type. Each filter does one and only one check.
I also remove the ItemType as it seems redundant - you can use classes themselves to determine the type.
Reuse the filters on anything you want :)
Hope this helps.