Mercurial > pub > bltoolkit
diff Source/Data/Linq/LinqExtensions.cs @ 0:f990fcb411a9
Копия текущей версии из github
author | cin |
---|---|
date | Thu, 27 Mar 2014 21:46:09 +0400 |
parents | |
children |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Source/Data/Linq/LinqExtensions.cs Thu Mar 27 21:46:09 2014 +0400 @@ -0,0 +1,716 @@ +using System; +using System.Linq; +using System.Linq.Expressions; +using System.Reflection; + +using JetBrains.Annotations; + +namespace BLToolkit.Data.Linq +{ + public static class LinqExtensions + { + #region Table Helpers + + static public Table<T> TableName<T>([NotNull] this Table<T> table, [NotNull] string name) + { + if (table == null) throw new ArgumentNullException("table"); + if (name == null) throw new ArgumentNullException("name"); + + table.Expression = Expression.Call( + null, + ((MethodInfo)MethodBase.GetCurrentMethod()).MakeGenericMethod(new[] { typeof(T) }), + new[] { table.Expression, Expression.Constant(name) }); + + return table; + } + + static public Table<T> DatabaseName<T>([NotNull] this Table<T> table, [NotNull] string name) + { + if (table == null) throw new ArgumentNullException("table"); + if (name == null) throw new ArgumentNullException("name"); + + table.Expression = Expression.Call( + null, + ((MethodInfo)MethodBase.GetCurrentMethod()).MakeGenericMethod(new[] { typeof(T) }), + new[] { table.Expression, Expression.Constant(name) }); + + return table; + } + + static public Table<T> OwnerName<T>([NotNull] this Table<T> table, [NotNull] string name) + { + if (table == null) throw new ArgumentNullException("table"); + if (name == null) throw new ArgumentNullException("name"); + + table.Expression = Expression.Call( + null, + ((MethodInfo)MethodBase.GetCurrentMethod()).MakeGenericMethod(new[] { typeof(T) }), + new[] { table.Expression, Expression.Constant(name) }); + + return table; + } + + #endregion + + #region Scalar Select + + static public T Select<T>([NotNull] this IDataContext dataContext, [NotNull, InstantHandle] Expression<Func<T>> selector) + { + if (dataContext == null) throw new ArgumentNullException("dataContext"); + if (selector == null) throw new ArgumentNullException("selector"); + + var q = new Table<T>(dataContext, selector); + + foreach (var item in q) + return item; + + throw new InvalidOperationException(); + } + + #endregion + + #region Delete + + public static int Delete<T>([NotNull] this IQueryable<T> source) + { + if (source == null) throw new ArgumentNullException("source"); + + return source.Provider.Execute<int>( + Expression.Call( + null, + ((MethodInfo)MethodBase.GetCurrentMethod()).MakeGenericMethod(new[] { typeof(T) }), + new[] { source.Expression })); + } + + public static int Delete<T>( + [NotNull, InstantHandle] this IQueryable<T> source, + [NotNull, InstantHandle] Expression<Func<T,bool>> predicate) + { + if (source == null) throw new ArgumentNullException("source"); + if (predicate == null) throw new ArgumentNullException("predicate"); + + return source.Provider.Execute<int>( + Expression.Call( + null, + ((MethodInfo)MethodBase.GetCurrentMethod()).MakeGenericMethod(new[] { typeof(T) }), + new[] { source.Expression, Expression.Quote(predicate) })); + } + + #endregion + + #region Update + + public static int Update<TSource,TTarget>( + [NotNull] this IQueryable<TSource> source, + [NotNull] Table<TTarget> target, + [NotNull, InstantHandle] Expression<Func<TSource,TTarget>> setter) + { + if (source == null) throw new ArgumentNullException("source"); + if (target == null) throw new ArgumentNullException("target"); + if (setter == null) throw new ArgumentNullException("setter"); + + return source.Provider.Execute<int>( + Expression.Call( + null, + ((MethodInfo)MethodBase.GetCurrentMethod()).MakeGenericMethod(new[] { typeof(TSource), typeof(TTarget) }), + new[] { source.Expression, ((IQueryable<TTarget>)target).Expression, Expression.Quote(setter) })); + } + + public static int Update<T>( + [NotNull] this IQueryable<T> source, + [NotNull, InstantHandle] Expression<Func<T,T>> setter) + { + if (source == null) throw new ArgumentNullException("source"); + if (setter == null) throw new ArgumentNullException("setter"); + + return source.Provider.Execute<int>( + Expression.Call( + null, + ((MethodInfo)MethodBase.GetCurrentMethod()).MakeGenericMethod(new[] { typeof(T) }), + new[] { source.Expression, Expression.Quote(setter) })); + } + + public static int Update<T>( + [NotNull] this IQueryable<T> source, + [NotNull, InstantHandle] Expression<Func<T,bool>> predicate, + [NotNull, InstantHandle] Expression<Func<T,T>> setter) + { + if (source == null) throw new ArgumentNullException("source"); + if (predicate == null) throw new ArgumentNullException("predicate"); + if (setter == null) throw new ArgumentNullException("setter"); + + return source.Provider.Execute<int>( + Expression.Call( + null, + ((MethodInfo)MethodBase.GetCurrentMethod()).MakeGenericMethod(new[] { typeof(T) }), + new[] { source.Expression, Expression.Quote(predicate), Expression.Quote(setter) })); + } + + public static int Update<T>([NotNull] this IUpdatable<T> source) + { + if (source == null) throw new ArgumentNullException("source"); + + var query = ((Updatable<T>)source).Query; + + return query.Provider.Execute<int>( + Expression.Call( + null, + ((MethodInfo)MethodBase.GetCurrentMethod()).MakeGenericMethod(new[] { typeof(T) }), + new[] { query.Expression })); + } + + class Updatable<T> : IUpdatable<T> + { + public IQueryable<T> Query; + } + + public static IUpdatable<T> AsUpdatable<T>([NotNull] this IQueryable<T> source) + { + if (source == null) throw new ArgumentNullException("source"); + + var query = source.Provider.CreateQuery<T>( + Expression.Call( + null, + ((MethodInfo)MethodBase.GetCurrentMethod()).MakeGenericMethod(new[] { typeof(T) }), + new[] { source.Expression })); + + return new Updatable<T> { Query = query }; + } + + public static IUpdatable<T> Set<T,TV>( + [NotNull] this IQueryable<T> source, + [NotNull, InstantHandle] Expression<Func<T,TV>> extract, + [NotNull, InstantHandle] Expression<Func<T,TV>> update) + { + if (source == null) throw new ArgumentNullException("source"); + if (extract == null) throw new ArgumentNullException("extract"); + if (update == null) throw new ArgumentNullException("update"); + + var query = source.Provider.CreateQuery<T>( + Expression.Call( + null, + ((MethodInfo)MethodBase.GetCurrentMethod()).MakeGenericMethod(new[] { typeof(T), typeof(TV) }), + new[] { source.Expression, Expression.Quote(extract), Expression.Quote(update) })); + + return new Updatable<T> { Query = query }; + } + + public static IUpdatable<T> Set<T,TV>( + [NotNull] this IUpdatable<T> source, + [NotNull, InstantHandle] Expression<Func<T,TV>> extract, + [NotNull, InstantHandle] Expression<Func<T,TV>> update) + { + if (source == null) throw new ArgumentNullException("source"); + if (extract == null) throw new ArgumentNullException("extract"); + if (update == null) throw new ArgumentNullException("update"); + + var query = ((Updatable<T>)source).Query; + + query = query.Provider.CreateQuery<T>( + Expression.Call( + null, + ((MethodInfo)MethodBase.GetCurrentMethod()).MakeGenericMethod(new[] { typeof(T), typeof(TV) }), + new[] { query.Expression, Expression.Quote(extract), Expression.Quote(update) })); + + return new Updatable<T> { Query = query }; + } + + public static IUpdatable<T> Set<T,TV>( + [NotNull] this IQueryable<T> source, + [NotNull, InstantHandle] Expression<Func<T,TV>> extract, + [NotNull, InstantHandle] Expression<Func<TV>> update) + { + if (source == null) throw new ArgumentNullException("source"); + if (extract == null) throw new ArgumentNullException("extract"); + if (update == null) throw new ArgumentNullException("update"); + + var query = source.Provider.CreateQuery<T>( + Expression.Call( + null, + ((MethodInfo)MethodBase.GetCurrentMethod()).MakeGenericMethod(new[] { typeof(T), typeof(TV) }), + new[] { source.Expression, Expression.Quote(extract), Expression.Quote(update) })); + + return new Updatable<T> { Query = query }; + } + + public static IUpdatable<T> Set<T,TV>( + [NotNull] this IUpdatable<T> source, + [NotNull, InstantHandle] Expression<Func<T,TV>> extract, + [NotNull, InstantHandle] Expression<Func<TV>> update) + { + if (source == null) throw new ArgumentNullException("source"); + if (extract == null) throw new ArgumentNullException("extract"); + if (update == null) throw new ArgumentNullException("update"); + + var query = ((Updatable<T>)source).Query; + + query = query.Provider.CreateQuery<T>( + Expression.Call( + null, + ((MethodInfo)MethodBase.GetCurrentMethod()).MakeGenericMethod(new[] { typeof(T), typeof(TV) }), + new[] { query.Expression, Expression.Quote(extract), Expression.Quote(update) })); + + return new Updatable<T> { Query = query }; + } + + public static IUpdatable<T> Set<T,TV>( + [NotNull] this IQueryable<T> source, + [NotNull, InstantHandle] Expression<Func<T,TV>> extract, + TV value) + { + if (source == null) throw new ArgumentNullException("source"); + if (extract == null) throw new ArgumentNullException("extract"); + + var query = source.Provider.CreateQuery<T>( + Expression.Call( + null, + ((MethodInfo)MethodBase.GetCurrentMethod()).MakeGenericMethod(new[] { typeof(T), typeof(TV) }), + new[] { source.Expression, Expression.Quote(extract), Expression.Constant(value, typeof(TV)) })); + + return new Updatable<T> { Query = query }; + } + + public static IUpdatable<T> Set<T,TV>( + [NotNull] this IUpdatable<T> source, + [NotNull, InstantHandle] Expression<Func<T,TV>> extract, + TV value) + { + if (source == null) throw new ArgumentNullException("source"); + if (extract == null) throw new ArgumentNullException("extract"); + + var query = ((Updatable<T>)source).Query; + + query = query.Provider.CreateQuery<T>( + Expression.Call( + null, + ((MethodInfo)MethodBase.GetCurrentMethod()).MakeGenericMethod(new[] { typeof(T), typeof(TV) }), + new[] { query.Expression, Expression.Quote(extract), Expression.Constant(value, typeof(TV)) })); + + return new Updatable<T> { Query = query }; + } + + #endregion + + #region Insert + + public static int Insert<T>( + [NotNull] this Table<T> target, + [NotNull, InstantHandle] Expression<Func<T>> setter) + { + if (target == null) throw new ArgumentNullException("target"); + if (setter == null) throw new ArgumentNullException("setter"); + + IQueryable<T> query = target; + + return query.Provider.Execute<int>( + Expression.Call( + null, + ((MethodInfo)MethodBase.GetCurrentMethod()).MakeGenericMethod(new[] { typeof(T) }), + new[] { query.Expression, Expression.Quote(setter) })); + } + + public static object InsertWithIdentity<T>( + [NotNull] this Table<T> target, + [NotNull, InstantHandle] Expression<Func<T>> setter) + { + if (target == null) throw new ArgumentNullException("target"); + if (setter == null) throw new ArgumentNullException("setter"); + + IQueryable<T> query = target; + + return query.Provider.Execute<object>( + Expression.Call( + null, + ((MethodInfo)MethodBase.GetCurrentMethod()).MakeGenericMethod(new[] { typeof(T) }), + new[] { query.Expression, Expression.Quote(setter) })); + } + + #region ValueInsertable + + class ValueInsertable<T> : IValueInsertable<T> + { + public IQueryable<T> Query; + } + + public static IValueInsertable<T> Into<T>(this IDataContext dataContext, [NotNull] Table<T> target) + { + if (target == null) throw new ArgumentNullException("target"); + + IQueryable<T> query = target; + + var q = query.Provider.CreateQuery<T>( + Expression.Call( + null, + ((MethodInfo)MethodBase.GetCurrentMethod()).MakeGenericMethod(new[] { typeof(T) }), + new[] { Expression.Constant(null, typeof(IDataContext)), query.Expression })); + + return new ValueInsertable<T> { Query = q }; + } + + public static IValueInsertable<T> Value<T,TV>( + [NotNull] this Table<T> source, + [NotNull, InstantHandle] Expression<Func<T,TV>> field, + [NotNull, InstantHandle] Expression<Func<TV>> value) + { + if (source == null) throw new ArgumentNullException("source"); + if (field == null) throw new ArgumentNullException("field"); + if (value == null) throw new ArgumentNullException("value"); + + var query = (IQueryable<T>)source; + + var q = query.Provider.CreateQuery<T>( + Expression.Call( + null, + ((MethodInfo)MethodBase.GetCurrentMethod()).MakeGenericMethod(new[] { typeof(T), typeof(TV) }), + new[] { query.Expression, Expression.Quote(field), Expression.Quote(value) })); + + return new ValueInsertable<T> { Query = q }; + } + + public static IValueInsertable<T> Value<T,TV>( + [NotNull] this Table<T> source, + [NotNull, InstantHandle] Expression<Func<T,TV>> field, + TV value) + { + if (source == null) throw new ArgumentNullException("source"); + if (field == null) throw new ArgumentNullException("field"); + + var query = (IQueryable<T>)source; + + var q = query.Provider.CreateQuery<T>( + Expression.Call( + null, + ((MethodInfo)MethodBase.GetCurrentMethod()).MakeGenericMethod(new[] { typeof(T), typeof(TV) }), + new[] { query.Expression, Expression.Quote(field), Expression.Constant(value, typeof(TV)) })); + + return new ValueInsertable<T> { Query = q }; + } + + public static IValueInsertable<T> Value<T,TV>( + [NotNull] this IValueInsertable<T> source, + [NotNull, InstantHandle] Expression<Func<T,TV>> field, + [NotNull, InstantHandle] Expression<Func<TV>> value) + { + if (source == null) throw new ArgumentNullException("source"); + if (field == null) throw new ArgumentNullException("field"); + if (value == null) throw new ArgumentNullException("value"); + + var query = ((ValueInsertable<T>)source).Query; + + var q = query.Provider.CreateQuery<T>( + Expression.Call( + null, + ((MethodInfo)MethodBase.GetCurrentMethod()).MakeGenericMethod(new[] { typeof(T), typeof(TV) }), + new[] { query.Expression, Expression.Quote(field), Expression.Quote(value) })); + + return new ValueInsertable<T> { Query = q }; + } + + public static IValueInsertable<T> Value<T,TV>( + [NotNull] this IValueInsertable<T> source, + [NotNull, InstantHandle] Expression<Func<T,TV>> field, + TV value) + { + if (source == null) throw new ArgumentNullException("source"); + if (field == null) throw new ArgumentNullException("field"); + + var query = ((ValueInsertable<T>)source).Query; + + var q = query.Provider.CreateQuery<T>( + Expression.Call( + null, + ((MethodInfo)MethodBase.GetCurrentMethod()).MakeGenericMethod(new[] { typeof(T), typeof(TV) }), + new[] { query.Expression, Expression.Quote(field), Expression.Constant(value, typeof(TV)) })); + + return new ValueInsertable<T> { Query = q }; + } + + public static int Insert<T>([NotNull] this IValueInsertable<T> source) + { + if (source == null) throw new ArgumentNullException("source"); + + var query = ((ValueInsertable<T>)source).Query; + + return query.Provider.Execute<int>( + Expression.Call( + null, + ((MethodInfo)MethodBase.GetCurrentMethod()).MakeGenericMethod(new[] { typeof(T) }), + new[] { query.Expression })); + } + + public static object InsertWithIdentity<T>([NotNull] this IValueInsertable<T> source) + { + if (source == null) throw new ArgumentNullException("source"); + + var query = ((ValueInsertable<T>)source).Query; + + return query.Provider.Execute<object>( + Expression.Call( + null, + ((MethodInfo)MethodBase.GetCurrentMethod()).MakeGenericMethod(new[] { typeof(T) }), + new[] { query.Expression })); + } + + #endregion + + #region SelectInsertable + + public static int Insert<TSource,TTarget>( + [NotNull] this IQueryable<TSource> source, + [NotNull] Table<TTarget> target, + [NotNull, InstantHandle] Expression<Func<TSource, TTarget>> setter) + { + if (source == null) throw new ArgumentNullException("source"); + if (target == null) throw new ArgumentNullException("target"); + if (setter == null) throw new ArgumentNullException("setter"); + + return source.Provider.Execute<int>( + Expression.Call( + null, + ((MethodInfo)MethodBase.GetCurrentMethod()).MakeGenericMethod(new[] { typeof(TSource), typeof(TTarget) }), + new[] { source.Expression, ((IQueryable<TTarget>)target).Expression, Expression.Quote(setter) })); + } + + public static object InsertWithIdentity<TSource,TTarget>( + [NotNull] this IQueryable<TSource> source, + [NotNull] Table<TTarget> target, + [NotNull, InstantHandle] Expression<Func<TSource,TTarget>> setter) + { + if (source == null) throw new ArgumentNullException("source"); + if (target == null) throw new ArgumentNullException("target"); + if (setter == null) throw new ArgumentNullException("setter"); + + return source.Provider.Execute<object>( + Expression.Call( + null, + ((MethodInfo)MethodBase.GetCurrentMethod()).MakeGenericMethod(new[] { typeof(TSource), typeof(TTarget) }), + new[] { source.Expression, ((IQueryable<TTarget>)target).Expression, Expression.Quote(setter) })); + } + + class SelectInsertable<T,TT> : ISelectInsertable<T,TT> + { + public IQueryable<T> Query; + } + + public static ISelectInsertable<TSource,TTarget> Into<TSource,TTarget>( + [NotNull] this IQueryable<TSource> source, + [NotNull] Table<TTarget> target) + { + if (target == null) throw new ArgumentNullException("target"); + + var q = source.Provider.CreateQuery<TSource>( + Expression.Call( + null, + ((MethodInfo)MethodBase.GetCurrentMethod()).MakeGenericMethod(new[] { typeof(TSource), typeof(TTarget) }), + new[] { source.Expression, ((IQueryable<TTarget>)target).Expression })); + + return new SelectInsertable<TSource,TTarget> { Query = q }; + } + + public static ISelectInsertable<TSource,TTarget> Value<TSource,TTarget,TValue>( + [NotNull] this ISelectInsertable<TSource,TTarget> source, + [NotNull, InstantHandle] Expression<Func<TTarget,TValue>> field, + [NotNull, InstantHandle] Expression<Func<TSource,TValue>> value) + { + if (source == null) throw new ArgumentNullException("source"); + if (field == null) throw new ArgumentNullException("field"); + if (value == null) throw new ArgumentNullException("value"); + + var query = ((SelectInsertable<TSource,TTarget>)source).Query; + + var q = query.Provider.CreateQuery<TSource>( + Expression.Call( + null, + ((MethodInfo)MethodBase.GetCurrentMethod()).MakeGenericMethod(new[] { typeof(TSource), typeof(TTarget), typeof(TValue) }), + new[] { query.Expression, Expression.Quote(field), Expression.Quote(value) })); + + return new SelectInsertable<TSource,TTarget> { Query = q }; + } + + public static ISelectInsertable<TSource,TTarget> Value<TSource,TTarget,TValue>( + [NotNull] this ISelectInsertable<TSource,TTarget> source, + [NotNull, InstantHandle] Expression<Func<TTarget,TValue>> field, + [NotNull, InstantHandle] Expression<Func<TValue>> value) + { + if (source == null) throw new ArgumentNullException("source"); + if (field == null) throw new ArgumentNullException("field"); + if (value == null) throw new ArgumentNullException("value"); + + var query = ((SelectInsertable<TSource,TTarget>)source).Query; + + var q = query.Provider.CreateQuery<TSource>( + Expression.Call( + null, + ((MethodInfo)MethodBase.GetCurrentMethod()).MakeGenericMethod(new[] { typeof(TSource), typeof(TTarget), typeof(TValue) }), + new[] { query.Expression, Expression.Quote(field), Expression.Quote(value) })); + + return new SelectInsertable<TSource,TTarget> { Query = q }; + } + + public static ISelectInsertable<TSource,TTarget> Value<TSource,TTarget,TValue>( + [NotNull] this ISelectInsertable<TSource,TTarget> source, + [NotNull, InstantHandle] Expression<Func<TTarget,TValue>> field, + TValue value) + { + if (source == null) throw new ArgumentNullException("source"); + if (field == null) throw new ArgumentNullException("field"); + + var query = ((SelectInsertable<TSource,TTarget>)source).Query; + + var q = query.Provider.CreateQuery<TSource>( + Expression.Call( + null, + ((MethodInfo)MethodBase.GetCurrentMethod()).MakeGenericMethod(new[] { typeof(TSource), typeof(TTarget), typeof(TValue) }), + new[] { query.Expression, Expression.Quote(field), Expression.Constant(value, typeof(TValue)) })); + + return new SelectInsertable<TSource,TTarget> { Query = q }; + } + + public static int Insert<TSource,TTarget>([NotNull] this ISelectInsertable<TSource,TTarget> source) + { + if (source == null) throw new ArgumentNullException("source"); + + var query = ((SelectInsertable<TSource,TTarget>)source).Query; + + return query.Provider.Execute<int>( + Expression.Call( + null, + ((MethodInfo)MethodBase.GetCurrentMethod()).MakeGenericMethod(new[] { typeof(TSource), typeof(TTarget) }), + new[] { query.Expression })); + } + + public static object InsertWithIdentity<TSource,TTarget>([NotNull] this ISelectInsertable<TSource,TTarget> source) + { + if (source == null) throw new ArgumentNullException("source"); + + var query = ((SelectInsertable<TSource,TTarget>)source).Query; + + return query.Provider.Execute<object>( + Expression.Call( + null, + ((MethodInfo)MethodBase.GetCurrentMethod()).MakeGenericMethod(new[] { typeof(TSource), typeof(TTarget) }), + new[] { query.Expression })); + } + + #endregion + + #endregion + + #region InsertOrUpdate + + public static int InsertOrUpdate<T>( + [NotNull] this Table<T> target, + [NotNull, InstantHandle] Expression<Func<T>> insertSetter, + [NotNull, InstantHandle] Expression<Func<T,T>> onDuplicateKeyUpdateSetter) + { + if (target == null) throw new ArgumentNullException("target"); + if (insertSetter == null) throw new ArgumentNullException("insertSetter"); + if (onDuplicateKeyUpdateSetter == null) throw new ArgumentNullException("onDuplicateKeyUpdateSetter"); + + IQueryable<T> query = target; + + return query.Provider.Execute<int>( + Expression.Call( + null, + ((MethodInfo)MethodBase.GetCurrentMethod()).MakeGenericMethod(new[] { typeof(T) }), + new[] { query.Expression, Expression.Quote(insertSetter), Expression.Quote(onDuplicateKeyUpdateSetter) })); + } + + public static int InsertOrUpdate<T>( + [NotNull] this Table<T> target, + [NotNull, InstantHandle] Expression<Func<T>> insertSetter, + [NotNull, InstantHandle] Expression<Func<T,T>> onDuplicateKeyUpdateSetter, + [NotNull, InstantHandle] Expression<Func<T>> keySelector) + { + if (target == null) throw new ArgumentNullException("target"); + if (insertSetter == null) throw new ArgumentNullException("insertSetter"); + if (onDuplicateKeyUpdateSetter == null) throw new ArgumentNullException("onDuplicateKeyUpdateSetter"); + if (keySelector == null) throw new ArgumentNullException("keySelector"); + + IQueryable<T> query = target; + + return query.Provider.Execute<int>( + Expression.Call( + null, + ((MethodInfo)MethodBase.GetCurrentMethod()).MakeGenericMethod(new[] { typeof(T) }), + new[] + { + query.Expression, + Expression.Quote(insertSetter), + Expression.Quote(onDuplicateKeyUpdateSetter), + Expression.Quote(keySelector) + })); + } + + #endregion + + #region Take / Skip / ElementAt + + public static IQueryable<TSource> Take<TSource>( + [NotNull] this IQueryable<TSource> source, + [NotNull, InstantHandle] Expression<Func<int>> count) + { + if (source == null) throw new ArgumentNullException("source"); + if (count == null) throw new ArgumentNullException("count"); + + return source.Provider.CreateQuery<TSource>( + Expression.Call( + null, + ((MethodInfo)MethodBase.GetCurrentMethod()).MakeGenericMethod(new[] { typeof(TSource) }), + new[] { source.Expression, Expression.Quote(count) })); + } + + public static IQueryable<TSource> Skip<TSource>( + [NotNull] this IQueryable<TSource> source, + [NotNull, InstantHandle] Expression<Func<int>> count) + { + if (source == null) throw new ArgumentNullException("source"); + if (count == null) throw new ArgumentNullException("count"); + + return source.Provider.CreateQuery<TSource>( + Expression.Call( + null, + ((MethodInfo)MethodBase.GetCurrentMethod()).MakeGenericMethod(new[] { typeof(TSource) }), + new[] { source.Expression, Expression.Quote(count) })); + } + + public static TSource ElementAt<TSource>( + [NotNull] this IQueryable<TSource> source, + [NotNull, InstantHandle] Expression<Func<int>> index) + { + if (source == null) throw new ArgumentNullException("source"); + if (index == null) throw new ArgumentNullException("index"); + + return source.Provider.Execute<TSource>( + Expression.Call( + null, + ((MethodInfo)MethodBase.GetCurrentMethod()).MakeGenericMethod(new[] { typeof(TSource) }), + new[] { source.Expression, Expression.Quote(index) })); + } + + public static TSource ElementAtOrDefault<TSource>( + [NotNull] this IQueryable<TSource> source, + [NotNull, InstantHandle] Expression<Func<int>> index) + { + if (source == null) throw new ArgumentNullException("source"); + if (index == null) throw new ArgumentNullException("index"); + + return source.Provider.Execute<TSource>( + Expression.Call( + null, + ((MethodInfo)MethodBase.GetCurrentMethod()).MakeGenericMethod(new[] { typeof(TSource) }), + new[] { source.Expression, Expression.Quote(index) })); + } + + #endregion + + #region Stub helpers + + static TOutput Where<TOutput,TSource,TInput>(this TInput source, Func<TSource,bool> predicate) + { + throw new InvalidOperationException(); + } + + #endregion + } +}