C#定制观察的集合 - 我应该使用成分还是继承? [英] C# Custom Observable Collection - Should I use Composition or Inheritance?

查看:109
本文介绍了C#定制观察的集合 - 我应该使用成分还是继承?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想创建一个自定义的观察的集合(在XAML可以绑定到),但我想跟踪这需要压倒一切的观察的集合方法的其他信息。 的ObservableCollection方法不是虚拟虽然,这意味着'覆盖'的唯一办法他们实际上只使用了'新'的关键字来隐藏它们。下面是我的意思了一个简单的例子:

I want to create a custom observable collection (can be bound to in XAML), but I want to track additional information which requires overriding observable collection methods. ObservableCollection methods are not virtual though, which means the only way to 'override' them is actually just to hide them using the 'new' keyword. Here is a simple example of what I mean:

//Tracks how many objects of each type are in this collection
class CustomCollectionInherited:ObservableCollection<Object>
{
    private Dictionary<Type, UInt32> _count = new Dictionary<Type,uint>();

    public UInt32 getTypeCount(Type T)
    {
        return _count[T];
    }

    #region Base Method 'Overrides'

    new public void Add(Object item)
    {
        base.Add(item);
        if (!_count.ContainsKey(item.GetType())) {
            _count[item.GetType()] = 1;
        } else {
            _count[item.GetType()] += 1;
        }
    }

    new public bool Remove(Object item)
    {
        if (base.Remove(item))
        {
            _count[item.GetType()] -= 1;
            return true;
        }
        return false;
    }

    #endregion
}

我有两个问题与此有关。第一个是,虽然有很多方法,我想从一个ObservableCollection继承,如统计员的INotifyCollectionChanged接口等,还有,我不希望继承许多方法。也就是说,修改的收集方法,如清除(),ClearItems(),插入()InsertItem(),和13人这将导致我收藏的类型计数不同步。这似乎是组成一个参数。

I have two problems with this. The first is that while there are many methods I want to inherit from an ObservableCollection, such as the enumerators, the INotifyCollectionChanged interface, etc., there are many methods which I do not want to inherit. Namely, methods that modify the collection, such as Clear(), ClearItems(), Insert(), InsertItem(), and 13 others which would cause my collection's type count to get out of sync. This seems to be an argument for composition.

第二个问题是上溯造型 - 程序员可能会意外地绕过我的自定义实现通过我的收藏以这样一种方式,它会上溯造型到继承的类型。例如:

The second problem is upcasting - a programmer might accidentally get around my custom implementations by using my collection in such a way that it gets upcast to the inherited type. For example:

    myCustomObj.AddToCollection( myCustomCollectionInherited );
...
void CustomObj.AddToCollection( Collection c )
{   
    c.Add(this);
}

这是一个pretty的人为的例子,但在这种情况下,继承的添加方法将被使用,而我收藏的种类数量将不同步了。似乎没有要解决这个办法,除非我收藏的监控base.CollectionChanged事件,每一次,这完全违背保持在O(1)时间计数的目的,重建的计数从零开始。

It's a pretty contrived example, but in such a case, the inherited 'Add' method would be used, and my collection's type count would get out of sync again. There doesn't seem to be any way around this unless my collection monitors the base.CollectionChanged event and rebuilds the count from scratch every time, which completely defeats the purpose of maintaining a count in O(1) time.

,我开始觉得合适的解决方案是创建一个类,它的包含一个ObservableCollection。但请记住,我需要这个绑定到XAML像一个观察的集合,所以我必须实现所有一个ObservableCollection实现,以便它可以绑定以同样的方式在用户界面相关的接口。下面是一个例子:

Based on those issues, I've started to think that the appropriate solution is to create a class which contains an ObservableCollection. But remember, I need this to bind to XAML like an observable collection, so I must implement all the relevant interfaces an ObservableCollection implements so that it can be bound to the UI in the same way. An example is below:

//Tracks how many objects of each type are in this collection
class CustomCollectionEncapsulated : IList<object>, INotifyCollectionChanged
{
    private ObservableCollection<Object> _base = new ObservableCollection<object>();
    private Dictionary<Type, UInt32> _count = new Dictionary<Type, uint>();

    public UInt32 getTypeCount(Type T)
    {
        return _count[T];
    }

    public void Add(object item)
    {
        _base.Add(item);
        if (!_count.ContainsKey(item.GetType())) {
            _count[item.GetType()] = 1;
        } else {
            _count[item.GetType()] += 1;
        }
    }

    public bool Remove(object item)
    {
        if (_base.Remove(item))
        {
            _count[item.GetType()] -= 1;
            return true;
        }
        return false;
    }
}

当然,上面的自己不编译,因为IList中实现的ICollection,IEnumerable的,IEnumerable的,所有这些都我需要实现的方法,依此类推,直到我最终有20个左右的额外的方法和数百个$ C $的行C所有这些说

Of course, the above on its own doesn't compile because IList implements ICollection, IEnumerable, IEnumerable, all of which have methods I need to implement, and so on until I end up having 20 or so extra methods and hundreds of lines of code all of which say

Type methodINeedToImplement(Params)
{
     return _base.methodINeedToImplement(Params);
}

Type methodINeedToImplement(Params)
{
     throw new NotImplementedException();
}

的主要原因继承是为了让程序员不需要做这些工作了95%的方法和事件,他们并没有改变。

The main reason for inheritance is so that a programmer does not need to do all this work for the 95% of methods and events they aren't changing.

所以,我该怎么办?我绝对无法说服我的老板,为了确保这一自定义集合的最好方法是使用的封装,并明确实施20个新的方法。与此同时,我们已经遇到了错误的地方使用这个自定义集合其他人都拧起来用,我们不支持基础的ObservableCollection方法,但无法通过继承隐藏。

So what do I do? I absolutely cannot convince my boss that the best way to secure this custom collection is to use encapsulation and explicitly implement 20 new methods. At the same time, we're already running into bugs where other people using this custom collection are screwing it up by using base ObservableCollection methods that we don't support, but can't hide via inheritance.

推荐答案

的ObservableCollection的设计是一个基类,你只是在寻找错误的方法,而不是公众的像添加,删除,清除等你应该重写受保护的虚拟的像InsertItem,移动选项等。检查文档一个完整的可重写的东西名单。

ObservableCollection is designed to be a base class, you are just looking at wrong methods, instead of public ones like Add, Remove, Clear, etc. you should override protected virtual ones like InsertItem, MoveItem, etc. Check documentation for a full list of overridable stuff.

这篇关于C#定制观察的集合 - 我应该使用成分还是继承?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆