private readonly PropertyInfo?count; // if null then object supports Slice method with Range parameter /// <summary> /// Initializes a new slice of collection or array. /// </summary> /// <param name="collection">The collection or array.</param> /// <param name="range">The requested range of collection or array. Should of type <see cref="Range"/>.</param> /// <exception cref="ArgumentException"><paramref name="collection"/> doesn't implement <c>Slice</c> method, <c>Length</c> or <c>Count</c> property; or <paramref name="range"/> is not of type <see cref="Range"/>.</exception> public SliceExpression(Expression collection, Expression range) { if (collection is null) { throw new ArgumentNullException(nameof(collection)); } if (range is null) { throw new ArgumentNullException(nameof(range)); } if (range.Type != typeof(Range)) { throw new ArgumentException(ExceptionMessages.TypeExpected <Range>(), nameof(range)); } var resolved = false; if (collection.Type.IsSZArray) { slice = null; count = null; resolved = true; } else if (collection.Type == typeof(string)) { slice = new Func <string, Range, string>(StringExtensions.Substring).Method; count = null; resolved = true; } else { foreach (var slice in GetSliceMethods(collection.Type)) { var parameters = slice.GetParameters(); if (parameters.LongLength == 1L && parameters[0].ParameterType == typeof(Range)) { count = null; this.slice = slice; resolved = true; break; } var intType = typeof(int); if (parameters.LongLength == 2L && parameters[0].ParameterType == intType && parameters[1].ParameterType == intType) { count = CollectionAccessExpression.GetCountProperty(collection.Type) ?? throw new ArgumentException(ExceptionMessages.CollectionExpected(collection.Type), nameof(collection)); this.slice = slice; resolved = true; break; } } } Range = resolved ? range : throw new ArgumentException(ExceptionMessages.CollectionExpected(collection.Type), nameof(collection)); Collection = collection; }
private readonly PropertyInfo?count; // if null then indexer != null because it has explicit Index parameter type /// <summary> /// Initializes a new collection access expression. /// </summary> /// <param name="collection">The expression representing collection.</param> /// <param name="index">The index of the element. Should be of type <see cref="System.Index"/>.</param> /// <exception cref="ArgumentException"><paramref name="collection"/> doesn't provide implicit support of Index expression.</exception> /// <seealso href="https://docs.microsoft.com/en-us/dotnet/csharp/language-reference/proposals/csharp-8.0/ranges">Ranges and Indicies</seealso> public CollectionAccessExpression(Expression collection, Expression index) { if (collection is null) { throw new ArgumentNullException(nameof(collection)); } if (index is null) { throw new ArgumentNullException(nameof(index)); } if (index.Type != typeof(Index)) { throw new ArgumentException(ExceptionMessages.TypeExpected <Index>(), nameof(index)); } var resolved = false; if (collection.Type.IsSZArray) { indexer = count = null; resolved = true; } else { foreach (var indexer in GetIndexers(collection.Type)) { var parameters = indexer.GetIndexParameters(); if (parameters.LongLength != 1L) { continue; } var firstParam = parameters[0].ParameterType; if (firstParam == typeof(Index)) { count = null; this.indexer = indexer; resolved = true; break; } if (firstParam == typeof(int)) { count = GetCountProperty(collection.Type) ?? throw new ArgumentException(ExceptionMessages.CollectionExpected(collection.Type), nameof(collection)); this.indexer = indexer; resolved = true; break; } } } Index = resolved ? index : throw new ArgumentException(ExceptionMessages.CollectionExpected(collection.Type), nameof(collection)); Collection = collection; }