| File: System\DirectoryServices\SchemaNameCollection.cs | Web Access |
| Project: src\runtime\src\libraries\System.DirectoryServices\src\System.DirectoryServices.csproj (System.DirectoryServices) |
// Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. using System.Collections; namespace System.DirectoryServices { /// <devdoc> /// Contains a list of schema names used for the <see cref='System.DirectoryServices.DirectoryEntries.SchemaFilter'/> property of a <see cref='System.DirectoryServices.DirectoryEntries'/>. /// </devdoc> public class SchemaNameCollection : IList { private readonly VariantPropGetter _propGetter; private readonly VariantPropSetter _propSetter; internal SchemaNameCollection(VariantPropGetter propGetter, VariantPropSetter propSetter) { _propGetter = propGetter; _propSetter = propSetter; } /// <devdoc> /// Gets or sets the object at the given index. /// </devdoc> public string? this[int index] { get { object?[] values = GetValue(); return (string?)values[index]; } set { object?[] values = GetValue(); values[index] = value; _propSetter(values); } } /// <devdoc> /// Gets the number of objects available on this entry. /// </devdoc> public int Count { get { object?[] values = GetValue(); return values.Length; } } /// <devdoc> /// Appends the value to the collection. /// </devdoc> public int Add(string? value) { object?[] oldValues = GetValue(); object?[] newValues = new object[oldValues.Length + 1]; for (int i = 0; i < oldValues.Length; i++) newValues[i] = oldValues[i]; newValues[newValues.Length - 1] = value; _propSetter(newValues); return newValues.Length - 1; } /// <devdoc> /// Appends the values to the collection. /// </devdoc> public void AddRange(string?[] value) { ArgumentNullException.ThrowIfNull(value); object?[] oldValues = GetValue(); object?[] newValues = new object[oldValues.Length + value.Length]; for (int i = 0; i < oldValues.Length; i++) newValues[i] = oldValues[i]; for (int i = oldValues.Length; i < newValues.Length; i++) newValues[i] = value[i - oldValues.Length]; _propSetter(newValues); } public void AddRange(SchemaNameCollection value) { ArgumentNullException.ThrowIfNull(value); object?[] oldValues = GetValue(); object?[] newValues = new object?[oldValues.Length + value.Count]; for (int i = 0; i < oldValues.Length; i++) newValues[i] = oldValues[i]; for (int i = oldValues.Length; i < newValues.Length; i++) newValues[i] = value[i - oldValues.Length]; _propSetter(newValues); } /// <devdoc> /// Removes all items from the collection. /// </devdoc> public void Clear() { _propSetter(Array.Empty<object>()); } /// <devdoc> /// Determines if the collection contains a specific value. /// </devdoc> public bool Contains(string? value) => IndexOf(value) != -1; public void CopyTo(string?[] stringArray, int index) { object?[] values = GetValue(); values.CopyTo(stringArray, index); } public IEnumerator GetEnumerator() { object?[] values = GetValue(); return values.GetEnumerator(); } private object?[] GetValue() { object? value = _propGetter(); if (value == null) return Array.Empty<object>(); else return (object?[])value; } /// <devdoc> /// Determines the index of a specific item in the collection. /// </devdoc> public int IndexOf(string? value) { object?[] values = GetValue(); for (int i = 0; i < values.Length; i++) { if (value == (string?)values[i]) return i; } return -1; } /// <devdoc> /// Inserts an item at the specified position in the collection. /// </devdoc> public void Insert(int index, string? value) { ArrayList tmpList = new ArrayList((ICollection)GetValue()); tmpList.Insert(index, value); _propSetter(tmpList.ToArray()); } /// <devdoc> /// Removes an item from the collection. /// </devdoc> public void Remove(string? value) { // this does take two scans of the array, but value isn't guaranteed to be there. int index = IndexOf(value); RemoveAt(index); } /// <devdoc> /// Removes the item at the specified index from the collection. /// </devdoc> public void RemoveAt(int index) { object?[] oldValues = GetValue(); if (index >= oldValues.Length || index < 0) throw new ArgumentOutOfRangeException(nameof(index)); object?[] newValues = new object[oldValues.Length - 1]; for (int i = 0; i < index; i++) newValues[i] = oldValues[i]; for (int i = index + 1; i < oldValues.Length; i++) newValues[i - 1] = oldValues[i]; _propSetter(newValues); } bool IList.IsReadOnly => false; bool IList.IsFixedSize => false; void ICollection.CopyTo(Array array, int index) { object?[] values = GetValue(); values.CopyTo(array, index); } bool ICollection.IsSynchronized => false; object ICollection.SyncRoot => this; object? IList.this[int index] { get => this[index]; set => this[index] = (string?)value; } int IList.Add(object? value) => Add((string?)value); bool IList.Contains(object? value) => Contains((string?)value); int IList.IndexOf(object? value) => IndexOf((string?)value); void IList.Insert(int index, object? value) => Insert(index, (string?)value); void IList.Remove(object? value) => Remove((string?)value); internal delegate object? VariantPropGetter(); internal delegate void VariantPropSetter(object? value); // this class and HintsDelegateWrapper exist only because you can't create // a delegate to a property's accessors. You have to supply methods. So these // classes wrap an object and supply properties as methods. internal sealed class FilterDelegateWrapper { private readonly UnsafeNativeMethods.IAdsContainer _obj; internal FilterDelegateWrapper(UnsafeNativeMethods.IAdsContainer wrapped) { _obj = wrapped; } public VariantPropGetter Getter => new VariantPropGetter(GetFilter); public VariantPropSetter Setter => new VariantPropSetter(SetFilter); private object? GetFilter() => _obj.Filter; private void SetFilter(object? value) => _obj.Filter = value; } } }