PageRenderTime 5ms CodeModel.GetById 6ms app.highlight 10ms RepoModel.GetById 1ms app.codeStats 0ms

/Bowling/Bowling.Domain/Concrete/EntityFramework/IRepositoryExtensions.cs

https://github.com/edqwerty1/Bowling
C# | 290 lines | 85 code | 8 blank | 197 comment | 22 complexity | 608d86abd4da140212d458bfddf0bfda MD5 | raw file
  1namespace Bowling.Domain.Abstract
  2{
  3    using System;
  4    using System.Collections.Generic;
  5    using System.Diagnostics.CodeAnalysis;
  6    using System.Diagnostics.Contracts;
  7    using System.Linq;
  8    using System.Linq.Expressions;
  9    using System.Threading;
 10    using System.Threading.Tasks;
 11
 12    /// <summary>
 13    /// Provides extension methods for the <see cref="IRepository{T}"/> and <see cref="IRepository{T}"/> interfaces.
 14    /// </summary>
 15    public static class IRepositoryExtensions
 16    {
 17        /// <summary>
 18        /// Retrieves all items in the repository satisfied by the specified query asynchronously.
 19        /// </summary>
 20        /// <typeparam name="T">The <see cref="Type">type</see> of item in the repository.</typeparam>
 21        /// <param name="repository">The extended <see cref="IRepository{T}">repository</see>.</param>
 22        /// <param name="queryShaper">The <see cref="Func{T,TResult}">function</see> that shapes the <see cref="IQueryable{T}">query</see> to execute.</param>
 23        /// <returns>A <see cref="Task{T}">task</see> containing the retrieved <see cref="IEnumerable{T}">sequence</see>
 24        /// of <typeparamref name="T">items</typeparamref>.</returns>
 25        /// <example>The following example demonstrates how to paginate the items in a repository using an example query.
 26        /// <code><![CDATA[
 27        /// using Microsoft.DesignPatterns.Examples;
 28        /// using System;
 29        /// using System.Collections.Generic;
 30        /// using System.Linq;
 31        /// using System.Threading;
 32        /// using System.Threading.Tasks;
 33        /// 
 34        /// public async static void Main()
 35        /// {
 36        ///     var index = 0;
 37        ///     var repository = new MyRepository();
 38        ///     
 39        ///     foreach ( var item in await repository.GetAsync( q => q.Where( i => i.FirstName.StartsWith( "Jo" ) ).OrderBy( i => i.LastName ) );
 40        ///         Console.WriteLine( i => i.ToString() );
 41        /// }
 42        /// ]]>
 43        /// </code></example>
 44        [SuppressMessage("Microsoft.Design", "CA1006:DoNotNestGenericTypesInMemberSignatures", Justification = "Required for generics support.")]
 45        [SuppressMessage("Microsoft.Design", "CA1062:Validate arguments of public methods", MessageId = "0", Justification = "Validated by a code contract.")]
 46        public static Task<IEnumerable<T>> GetAsync<T>(this IRepository<T> repository, Func<IQueryable<T>, IQueryable<T>> queryShaper) where T : class
 47        {
 48            Contract.Requires(repository != null);
 49            Contract.Requires(queryShaper != null);
 50            Contract.Ensures(Contract.Result<Task<IEnumerable<T>>>() != null);
 51            return repository.GetAsync(queryShaper, CancellationToken.None);
 52        }
 53
 54        /// <summary>
 55        /// Retrieves a query result asynchronously.
 56        /// </summary>
 57        /// <typeparam name="T">The <see cref="Type">type</see> of item in the repository.</typeparam>
 58        /// <typeparam name="TResult">The <see cref="Type">type</see> of result to retrieve.</typeparam>
 59        /// <param name="repository">The extended <see cref="IRepository{T}">repository</see>.</param>
 60        /// <param name="queryShaper">The <see cref="Func{T,TResult}">function</see> that shapes the <see cref="IQueryable{T}">query</see> to execute.</param>
 61        /// <returns>A <see cref="Task{T}">task</see> containing the <typeparamref name="TResult">result</typeparamref> of the operation.</returns>
 62        [SuppressMessage("Microsoft.Design", "CA1006:DoNotNestGenericTypesInMemberSignatures", Justification = "Required for generics support.")]
 63        [SuppressMessage("Microsoft.Design", "CA1062:Validate arguments of public methods", MessageId = "0", Justification = "Validated by a code contract.")]
 64        public static Task<TResult> GetAsync<T, TResult>(this IRepository<T> repository, Func<IQueryable<T>, TResult> queryShaper) where T : class
 65        {
 66            Contract.Requires(repository != null);
 67            Contract.Requires(queryShaper != null);
 68            Contract.Ensures(Contract.Result<Task<TResult>>() != null);
 69            return repository.GetAsync(queryShaper, CancellationToken.None);
 70        }
 71
 72        /// <summary>
 73        /// Retrieves all items in the repository asynchronously.
 74        /// </summary>
 75        /// <typeparam name="T">The <see cref="Type">type</see> of item in the repository.</typeparam>
 76        /// <param name="repository">The extended <see cref="IRepository{T}">repository</see>.</param>
 77        /// <returns>A <see cref="Task{T}">task</see> containing the <see cref="IEnumerable{T}">sequence</see>
 78        /// of all <typeparamref name="T">items</typeparamref> in the repository.</returns>
 79        /// <example>The following example demonstrates how to retrieve all items in a repository.
 80        /// <code><![CDATA[
 81        /// using Microsoft.DesignPatterns.Examples;
 82        /// using System;
 83        /// using System.Collections.Generic;
 84        /// using System.Linq;
 85        /// using System.Threading;
 86        /// using System.Threading.Tasks;
 87        /// 
 88        /// public async static void Main()
 89        /// {
 90        ///     var repository = new MyRepository();
 91        ///     
 92        ///     foreach ( var item in await repository.GetAllAsync( i => i.LastName == "Doe" ) )
 93        ///         Console.WriteLine( item.ToString() );
 94        /// }
 95        /// ]]>
 96        /// </code></example>
 97        [SuppressMessage("Microsoft.Design", "CA1006:DoNotNestGenericTypesInMemberSignatures", Justification = "Required for generics support.")]
 98        [SuppressMessage("Microsoft.Design", "CA1062:Validate arguments of public methods", MessageId = "0", Justification = "Validated by a code contract.")]
 99        public static Task<IEnumerable<T>> GetAllAsync<T>(this IRepository<T> repository) where T : class
100        {
101            Contract.Requires(repository != null);
102            Contract.Ensures(Contract.Result<Task<IEnumerable<T>>>() != null);
103            return repository.GetAsync(q => q, CancellationToken.None);
104        }
105
106        /// <summary>
107        /// Retrieves all items in the repository asynchronously.
108        /// </summary>
109        /// <typeparam name="T">The <see cref="Type">type</see> of item in the repository.</typeparam>
110        /// <param name="repository">The extended <see cref="IRepository{T}">repository</see>.</param>
111        /// <param name="cancellationToken">The <see cref="CancellationToken">cancellation token</see> that can be used to cancel the operation.</param>
112        /// <returns>A <see cref="Task{T}">task</see> containing the <see cref="IEnumerable{T}">sequence</see>
113        /// of all <typeparamref name="T">items</typeparamref> in the repository.</returns>
114        /// <example>The following example demonstrates how to retrieve all items in a repository.
115        /// <code><![CDATA[
116        /// using Microsoft.DesignPatterns.Examples;
117        /// using System;
118        /// using System.Collections.Generic;
119        /// using System.Linq;
120        /// using System.Threading;
121        /// using System.Threading.Tasks;
122        /// 
123        /// public async static void Main()
124        /// {
125        ///     var repository = new MyRepository();
126        ///     var cancellationToken = new CancellationToken();
127        ///     
128        ///     foreach ( var item in await repository.GetAllAsync( i => i.LastName == "Doe", cancellationToken ) )
129        ///         Console.WriteLine( item.ToString() );
130        /// }
131        /// ]]>
132        /// </code></example>
133        [SuppressMessage("Microsoft.Design", "CA1006:DoNotNestGenericTypesInMemberSignatures", Justification = "Required for generics support.")]
134        [SuppressMessage("Microsoft.Design", "CA1062:Validate arguments of public methods", MessageId = "0", Justification = "Validated by a code contract.")]
135        public static Task<IEnumerable<T>> GetAllAsync<T>(this IRepository<T> repository, CancellationToken cancellationToken) where T : class
136        {
137            Contract.Requires(repository != null);
138            Contract.Ensures(Contract.Result<Task<IEnumerable<T>>>() != null);
139            return repository.GetAsync(q => q, cancellationToken);
140        }
141
142        /// <summary>
143        /// Searches for items in the repository that match the specified predicate asynchronously.
144        /// </summary>
145        /// <typeparam name="T">The <see cref="Type">type</see> of item in the repository.</typeparam>
146        /// <param name="repository">The extended <see cref="IRepository{T}">repository</see>.</param>
147        /// <param name="predicate">The <see cref="Expression{T}">expression</see> representing the predicate used to
148        /// match the requested <typeparamref name="T">items</typeparamref>.</param>
149        /// <returns>A <see cref="Task{T}">task</see> containing the matched <see cref="IEnumerable{T}">sequence</see>
150        /// of <typeparamref name="T">items</typeparamref>.</returns>
151        /// <example>The following example demonstrates how to find items in a repository.
152        /// <code><![CDATA[
153        /// using Microsoft.DesignPatterns.Examples;
154        /// using System;
155        /// using System.Collections.Generic;
156        /// using System.Linq;
157        /// using System.Threading;
158        /// using System.Threading.Tasks;
159        /// 
160        /// public async static void Main()
161        /// {
162        ///     var repository = new MyRepository();
163        ///     var items = await repository.FindByAsync( i => i.LastName == "Doe" );
164        ///     items.ForEach( i => Console.WriteLine( i.ToString() ) );
165        /// }
166        /// ]]>
167        /// </code></example>
168        [SuppressMessage("Microsoft.Design", "CA1006:DoNotNestGenericTypesInMemberSignatures", Justification = "Required for generics support.")]
169        [SuppressMessage("Microsoft.Design", "CA1062:Validate arguments of public methods", MessageId = "0", Justification = "Validated by a code contract.")]
170        public static Task<IEnumerable<T>> FindByAsync<T>(this IRepository<T> repository, Expression<Func<T, bool>> predicate) where T : class
171        {
172            Contract.Requires(repository != null);
173            Contract.Requires(predicate != null);
174            Contract.Ensures(Contract.Result<Task<IEnumerable<T>>>() != null);
175            return repository.GetAsync(q => q.Where(predicate), CancellationToken.None);
176        }
177
178        /// <summary>
179        /// Searches for items in the repository that match the specified predicate asynchronously.
180        /// </summary>
181        /// <typeparam name="T">The <see cref="Type">type</see> of item in the repository.</typeparam>
182        /// <param name="repository">The extended <see cref="IRepository{T}">repository</see>.</param>
183        /// <param name="predicate">The <see cref="Expression{T}">expression</see> representing the predicate used to
184        /// match the requested <typeparamref name="T">items</typeparamref>.</param>
185        /// <param name="cancellationToken">The <see cref="CancellationToken">cancellation token</see> that can be used to cancel the operation.</param>
186        /// <returns>A <see cref="Task{T}">task</see> containing the matched <see cref="IEnumerable{T}">sequence</see>
187        /// of <typeparamref name="T">items</typeparamref>.</returns>
188        /// <example>The following example demonstrates how to find items in a repository.
189        /// <code><![CDATA[
190        /// using Microsoft.DesignPatterns.Examples;
191        /// using System;
192        /// using System.Collections.Generic;
193        /// using System.Linq;
194        /// using System.Threading;
195        /// using System.Threading.Tasks;
196        /// 
197        /// public async static void Main()
198        /// {
199        ///     var repository = new MyRepository();
200        ///     var cancellationToken = new CancellationToken();
201        ///     var items = await repository.FindByAsync( i => i.LastName == "Doe", cancellationToken );
202        ///     items.ForEach( i => Console.WriteLine( i.ToString() ) );
203        /// }
204        /// ]]>
205        /// </code></example>
206        [SuppressMessage("Microsoft.Design", "CA1006:DoNotNestGenericTypesInMemberSignatures", Justification = "Required for generics support.")]
207        [SuppressMessage("Microsoft.Design", "CA1062:Validate arguments of public methods", MessageId = "0", Justification = "Validated by a code contract.")]
208        public static Task<IEnumerable<T>> FindByAsync<T>(this IRepository<T> repository, Expression<Func<T, bool>> predicate, CancellationToken cancellationToken) where T : class
209        {
210            Contract.Requires(repository != null);
211            Contract.Requires(predicate != null);
212            Contract.Ensures(Contract.Result<Task<IEnumerable<T>>>() != null);
213            return repository.GetAsync(q => q.Where(predicate), cancellationToken);
214        }
215
216        /// <summary>
217        /// Retrieves a single item in the repository matching the specified predicate asynchronously.
218        /// </summary>
219        /// <typeparam name="T">The <see cref="Type">type</see> of item in the repository.</typeparam>
220        /// <param name="repository">The extended <see cref="IRepository{T}">repository</see>.</param>
221        /// <param name="predicate">The <see cref="Expression{T}">expression</see> representing the predicate used to
222        /// match the requested <typeparamref name="T">item</typeparamref>.</param>
223        /// <returns>A <see cref="Task{T}">task</see> containing the matched <typeparamref name="T">item</typeparamref>
224        /// or null if no match was found.</returns>
225        /// <example>The following example demonstrates how to retrieve a single item from a repository.
226        /// <code><![CDATA[
227        /// using Microsoft.DesignPatterns.Examples;
228        /// using System;
229        /// using System.Collections.Generic;
230        /// using System.Linq;
231        /// using System.Threading;
232        /// using System.Threading.Tasks;
233        /// 
234        /// public async static void Main()
235        /// {
236        ///     var repository = new MyRepository();
237        ///     var item = await repository.GetSingleAsync( i => i.Id == 1 );
238        ///     Console.WriteLine( item.ToString() );
239        /// }
240        /// ]]>
241        /// </code></example>
242        [SuppressMessage("Microsoft.Design", "CA1006:DoNotNestGenericTypesInMemberSignatures", Justification = "Required for generics support.")]
243        [SuppressMessage("Microsoft.Design", "CA1062:Validate arguments of public methods", MessageId = "0", Justification = "Validated by a code contract.")]
244        public static Task<T> GetSingleAsync<T>(this IRepository<T> repository, Expression<Func<T, bool>> predicate) where T : class
245        {
246            Contract.Requires(repository != null);
247            Contract.Requires(predicate != null);
248            Contract.Ensures(Contract.Result<Task<T>>() != null);
249            return repository.GetSingleAsync(predicate, CancellationToken.None);
250        }
251
252        /// <summary>
253        /// Retrieves a single item in the repository matching the specified predicate asynchronously.
254        /// </summary>
255        /// <typeparam name="T">The <see cref="Type">type</see> of item in the repository.</typeparam>
256        /// <param name="repository">The extended <see cref="IRepository{T}">repository</see>.</param>
257        /// <param name="predicate">The <see cref="Expression{T}">expression</see> representing the predicate used to
258        /// match the requested <typeparamref name="T">item</typeparamref>.</param>
259        /// <param name="cancellationToken">The <see cref="CancellationToken">cancellation token</see> that can be used to cancel the operation.</param>
260        /// <returns>A <see cref="Task{T}">task</see> containing the matched <typeparamref name="T">item</typeparamref>
261        /// or null if no match was found.</returns>
262        /// <example>The following example demonstrates how to retrieve a single item from a repository.
263        /// <code><![CDATA[
264        /// using Microsoft.DesignPatterns.Examples;
265        /// using System;
266        /// using System.Collections.Generic;
267        /// using System.Linq;
268        /// using System.Threading;
269        /// using System.Threading.Tasks;
270        /// 
271        /// public async static void Main()
272        /// {
273        ///     var repository = new MyRepository();
274        ///     var item = await repository.GetSingleAsync( i => i.Id == 1 );
275        ///     Console.WriteLine( item.ToString() );
276        /// }
277        /// ]]>
278        /// </code></example>
279        [SuppressMessage("Microsoft.Design", "CA1006:DoNotNestGenericTypesInMemberSignatures", Justification = "Required for generics support.")]
280        [SuppressMessage("Microsoft.Design", "CA1062:Validate arguments of public methods", MessageId = "0", Justification = "Validated by a code contract.")]
281        public static async Task<T> GetSingleAsync<T>(this IRepository<T> repository, Expression<Func<T, bool>> predicate, CancellationToken cancellationToken) where T : class
282        {
283            Contract.Requires(repository != null);
284            Contract.Requires(predicate != null);
285            Contract.Ensures(Contract.Result<Task<T>>() != null);
286            var items = await repository.GetAsync(q => q.Where(predicate), cancellationToken);
287            return items.SingleOrDefault();
288        }
289    }
290}