File: Shared\Options\ListValue.cs
Web Access
Project: src\src\dotnet-svcutil\lib\src\dotnet-svcutil-lib.csproj (dotnet-svcutil-lib)
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
//--------------------------------------------------------------------------------------------
// C`opyright(c) 2015 Microsoft Corporation
//--------------------------------------------------------------------------------------------
 
using System;
using System.Collections;
using System.Collections.Generic;
using System.Globalization;
using System.Linq;
 
namespace Microsoft.Tools.ServiceModel.Svcutil
{
    /// <summary>
    /// Represents an option that can be specified multiple times in the command line.
    /// </summary>
    internal class ListValue<TValue> : ICollection, IList<TValue>, IList
    {
        private List<TValue> InnerList { get; set; } = new List<TValue>();
        public ListValueOption<TValue> Owner { get; set; }
 
        public event EventHandler<ListOptionEventArgs> Inserting;
        public event EventHandler<ListOptionEventArgs> Inserted;
        public event EventHandler<ListOptionEventArgs> Removing;
        public event EventHandler<ListOptionEventArgs> Removed;
 
        public void Insert(int index, TValue value)
        {
            if (this.Contains(value))
            {
                throw new ArgumentException(string.Format(CultureInfo.CurrentCulture, Shared.Resources.ErrorOptionDuplicateValueFormat, this.Owner.Name, value));
            }
            var e = new ListOptionEventArgs(value);
            this.Inserting?.Invoke(this, e);
            this.InnerList.Insert(index, CastValue(e.Value));
            this.Inserted?.Invoke(this, e);
        }
        public void RemoveAt(int index)
        {
            var e = new ListOptionEventArgs(null);
            this.Removing?.Invoke(this, e);
            this.InnerList.RemoveAt(index);
            this.Removed?.Invoke(this, e);
        }
 
        public void ReplaceAt(int idx, TValue value)
        {
            RemoveAt(idx);
            Insert(idx, value);
        }
 
        private TValue CastValue(object value)
        {
            OptionValueParser.ThrowInvalidValueIf(value == null || value.GetType() != typeof(TValue), value, this.Owner);
            return (TValue)value;
        }
 
        #region interface methods
        public bool IsFixedSize { get { return false; } }
 
        public bool IsReadOnly { get { return false; } }
 
        bool IList.IsReadOnly { get { return this.IsReadOnly; } }
 
        public int Count { get { return this.InnerList.Count; } }
 
        int ICollection.Count { get { return this.Count; } }
 
        public bool IsSynchronized { get { return false; } }
 
        bool ICollection.IsSynchronized { get { return this.IsSynchronized; } }
 
        public object SyncRoot { get { return this.InnerList; } }
 
        object ICollection.SyncRoot { get { return this.SyncRoot; } }
 
        bool IList.IsFixedSize { get { return false; } }
 
        public TValue this[int index]
        {
            get { return this.InnerList[index]; }
            set { ReplaceAt(index, value); }
        }
 
        object IList.this[int index]
        {
            get { return this[index]; }
            set { this[index] = CastValue(value); }
        }
 
        int IList.Add(object value)
        {
            this.Add(OptionValueParser.ParseValue<TValue>(value, this.Owner));
            return this.Count - 1;
        }
 
        public int Add(TValue value)
        {
            Insert(this.Count, value);
            return this.Count - 1;
        }
 
        public void AddRange(IEnumerable<TValue> collection)
        {
            foreach (var item in collection)
            {
                this.Add(item);
            }
        }
 
        void ICollection<TValue>.Add(TValue value)
        {
            this.Add(value);
        }
 
        void IList.Insert(int index, object value)
        {
            this.Insert(index, CastValue(value));
        }
 
        public void Clear()
        {
            for (int idx = this.InnerList.Count - 1; idx >= 0; idx--)
            {
                RemoveAt(idx);
            }
        }
 
        void IList.Clear()
        {
            this.Clear();
        }
 
        public bool Contains(TValue value)
        {
            return this.InnerList.Contains(value);
        }
 
        bool IList.Contains(object value)
        {
            return this.Contains(CastValue(value));
        }
 
        public int IndexOf(TValue value)
        {
            return this.InnerList.IndexOf(value);
        }
 
        int IList.IndexOf(object value)
        {
            return this.IndexOf(CastValue(value));
        }
 
        void IList.Remove(object value)
        {
            Remove(CastValue(value));
        }
 
        void IList.RemoveAt(int index)
        {
            this.RemoveAt(index);
        }
 
        public bool Remove(TValue value)
        {
            int idx = this.IndexOf(value);
            if (idx != -1)
            {
                RemoveAt(idx);
                return true;
            }
            return false;
        }
 
        public void Sort()
        {
            this.InnerList.Sort();
        }
 
        public void CopyTo(Array array, int index)
        {
            this.CopyTo(array, index);
        }
 
        void ICollection.CopyTo(Array array, int index)
        {
            this.CopyTo(array, index);
        }
 
        public void CopyTo(TValue[] array, int index)
        {
            this.InnerList.CopyTo(array, index);
        }
 
        public IEnumerator GetEnumerator()
        {
            return this.InnerList.GetEnumerator();
        }
 
        IEnumerator IEnumerable.GetEnumerator()
        {
            return this.InnerList.GetEnumerator();
        }
 
        IEnumerator<TValue> IEnumerable<TValue>.GetEnumerator()
        {
            return this.InnerList.GetEnumerator();
        }
        #endregion
 
        public override string ToString()
        {
            var value = this.InnerList.Count > 0 ? this.InnerList.Select(i => $"\"{i}\"").Aggregate((str, s) => $"{str}, {s}") : string.Empty;
            return value;
        }
    }
 
    public class ListOptionEventArgs : EventArgs
    {
        public object Value { get; set; }
        public ListOptionEventArgs(object value)
        {
            this.Value = value;
        }
    }
}