ICollection属性和封装

时间:2018-06-14 11:26:45

标签: c# domain-driven-design

考虑到我想封装它们,为我的属性使用接口是不好的做法吗?

public class Order
{
    private readonly ICollection<OrderItem> _orderItems;
    public IReadOnlyCollection OrderItems => _orderItems; // not possible without ToList
}

没有简单的方法来公开它,因为无法首先使用IReadOnlyCollectionIEnumerable转换为ICollectionToList,而无需首先使用private readonly Collection<OrderItem> _orderItems; 复制整个集合。

我应该将其定义为:

private readonly HashSet<OrderItem> _orderItems;

private readonly List<OrderItem> _orderItems;

    callback = CustomJS(args={}, code="""
        let geometry = cb_data['geometry'];
        let x0 = geometry['x0'];
        let x1 = geometry['x1'];
        let event = new CustomEvent('MetricSelected', { detail: [x0, x1]});
        let elm = document.getElementById('metric_selected');
        elm.dispatchEvent(event);      
    """)

代替?

2 个答案:

答案 0 :(得分:1)

您应遵循的规则是私有成员仅对定义它们的类可见,因此您可以将类型定义为List<T>Hashset<T>Collection<T>,其他开发人员如果稍后修改类型,则使用您的班级程序集不会受到重大更改的影响。

只要您知道Hasset<T> vs List<T>List<T> vs Collection<T>之间的区别,就可以从问题中选择三种替代方案中的一种。

请删除界面ICollection<OrderItem>作为私有字段的类型,如果您不想在{{1}中调用ToList(),请使用具体的课程实施。

答案 1 :(得分:0)

您可以编写自己的扩展名以将ICollection转换为IReadOnlyCollection

public static class CollectionExtensions
{
    public static IReadOnlyCollection<T> AsReadOnly<T>(this ICollection<T> source)
    {
        if (source == null)
        {
            throw new ArgumentNullException("source");
        }
        return source as IReadOnlyCollection<T> ?? new ReadOnlyCollectionAdapter<T>(source);
    }
    sealed class ReadOnlyCollectionAdapter<T> : IReadOnlyCollection<T>
    {
        ICollection<T> source;
        public ReadOnlyCollectionAdapter(ICollection<T> source) { this.source = source; }
        public int Count { get { return source.Count; } }
        public IEnumerator<T> GetEnumerator() { return source.GetEnumerator(); }
        IEnumerator IEnumerable.GetEnumerator() { return GetEnumerator(); }
    }
}