Last active
September 13, 2015 17:07
-
-
Save jasonmitchell/62905f39a21979f14f06 to your computer and use it in GitHub Desktop.
Generic Repository
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
namespace Sample.Repositories.Specifications | |
{ | |
using System; | |
using System.Linq; | |
using System.Linq.Expressions; | |
internal class AndSpecification<T> : ISpecification<T> | |
{ | |
private readonly ISpecification<T> left; | |
private readonly ISpecification<T> right; | |
public AndSpecification(ISpecification<T> left, ISpecification<T> right) | |
{ | |
this.left = left; | |
this.right = right; | |
} | |
public Expression<Func<T, bool>> IsSatisifiedBy() | |
{ | |
var leftExpression = left.IsSatisifiedBy(); | |
var rightExpression = right.IsSatisifiedBy(); | |
var parameter = leftExpression.Parameters.Single(); | |
var body = Expression.AndAlso(leftExpression.Body, SpecificationParameterRebinder.ReplaceParameter(rightExpression.Body, parameter)); | |
return Expression.Lambda<Func<T, bool>>(body, parameter); | |
} | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
namespace Sample.Specifications | |
{ | |
using System; | |
using System.Linq.Expressions; | |
using Repositories.Models; | |
using Repositories.Specifications; | |
public class GetByFirstName : ISpecification<Person> | |
{ | |
private readonly string firstName; | |
public GetByFirstName(string firstName) | |
{ | |
this.firstName = firstName; | |
} | |
public Expression<Func<Person, bool>> IsSatisifiedBy() | |
{ | |
return x => x.FirstName == firstName; | |
} | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
namespace Sample.Specifications | |
{ | |
using System; | |
using System.Linq.Expressions; | |
using Repositories.Models; | |
using Repositories.Specifications; | |
public class GetByLastName : ISpecification<Person> | |
{ | |
private readonly string lastName; | |
public GetByLastName(string lastName) | |
{ | |
this.lastName = lastName; | |
} | |
public Expression<Func<Person, bool>> IsSatisifiedBy() | |
{ | |
return x => x.LastName == lastName; | |
} | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
namespace Sample.Repositories.Specifications | |
{ | |
using System; | |
using System.Linq.Expressions; | |
public interface ISpecification<T> | |
{ | |
Expression<Func<T, bool>> IsSatisifiedBy(); | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
namespace Sample.Repositories.Specifications | |
{ | |
using System; | |
using System.Linq.Expressions; | |
internal class NotSpecification<T> : ISpecification<T> | |
{ | |
private readonly ISpecification<T> specification; | |
public NotSpecification(ISpecification<T> specification) | |
{ | |
this.specification = specification; | |
} | |
public Expression<Func<T, bool>> IsSatisifiedBy() | |
{ | |
var expression = specification.IsSatisifiedBy(); | |
var parameter = expression.Parameters[0]; | |
var body = Expression.Not(expression.Body); | |
return Expression.Lambda<Func<T, bool>>(body, parameter); | |
} | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
namespace Sample.Repositories.Specifications | |
{ | |
using System; | |
using System.Linq; | |
using System.Linq.Expressions; | |
internal class OrSpecification<T> : ISpecification<T> | |
{ | |
private readonly ISpecification<T> left; | |
private readonly ISpecification<T> right; | |
public OrSpecification(ISpecification<T> left, ISpecification<T> right) | |
{ | |
this.left = left; | |
this.right = right; | |
} | |
public Expression<Func<T, bool>> IsSatisifiedBy() | |
{ | |
var leftExpression = left.IsSatisifiedBy(); | |
var rightExpression = right.IsSatisifiedBy(); | |
var parameter = leftExpression.Parameters.Single(); | |
var body = Expression.OrElse(leftExpression.Body, SpecificationParameterRebinder.ReplaceParameter(rightExpression.Body, parameter)); | |
return Expression.Lambda<Func<T, bool>>(body, parameter); | |
} | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
namespace Sample | |
{ | |
using System; | |
using System.Configuration; | |
using Repositories; | |
using Repositories.Models; | |
using Repositories.Specifications; | |
using Specifications; | |
class Program | |
{ | |
static void Main(string[] args) | |
{ | |
var connectionString = ConfigurationManager.ConnectionStrings["Demo"].ConnectionString; | |
using (var context = new SampleContext(connectionString)) | |
{ | |
// IQUERYABLE REPOSITORY | |
var repository = new QueryableRepository(context); | |
var people = repository.Query<Person>(x => x.FirstName == "Jason").ToList(); | |
// OR | |
//var people = repository.Query<Person>().Where(x => x.FirstName == "Jason").ToList(); | |
// WHY NOT JUST USE THE CONTEXT?? | |
//var people = context.People.Where(x => x.FirstName == "Jason").ToList(); | |
Console.WriteLine("Found {0} people", people.Count); | |
Console.ReadLine(); | |
} | |
} | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
namespace Sample | |
{ | |
using System; | |
using System.Configuration; | |
using Repositories; | |
using Repositories.Models; | |
using Repositories.Specifications; | |
using Specifications; | |
class Program | |
{ | |
static void Main(string[] args) | |
{ | |
var connectionString = ConfigurationManager.ConnectionStrings["Demo"].ConnectionString; | |
using (var context = new SampleContext(connectionString)) | |
{ | |
var repository = new SpecificationRepository(context); | |
var specification = new GetByFirstName("Jason").And(new GetByLastName("Mitchell")); | |
var people = repository.Find(specification); | |
Console.WriteLine("Found {0} people", people.Count); | |
Console.ReadLine(); | |
} | |
} | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
namespace Sample.Repositories | |
{ | |
using System; | |
using System.Data.Entity; | |
using System.Linq; | |
using System.Linq.Expressions; | |
public class QueryableRepository | |
{ | |
private readonly DbContext context; | |
public QueryableRepository(DbContext context) | |
{ | |
this.context = context; | |
} | |
public IQueryable<T> Query<T>(Expression<Func<T, bool>> predicate = null) where T : class | |
{ | |
var query = (IQueryable<T>)context.Set<T>(); | |
if (predicate != null) | |
{ | |
query = query.Where(predicate); | |
} | |
return query; | |
} | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
namespace Sample.Repositories.Specifications | |
{ | |
using System.Linq.Expressions; | |
internal class SpecificationParameterRebinder : ExpressionVisitor | |
{ | |
private readonly ParameterExpression specificationParameter; | |
private SpecificationParameterRebinder(ParameterExpression specificationParameter) | |
{ | |
this.specificationParameter = specificationParameter; | |
} | |
public static Expression ReplaceParameter(Expression expression, ParameterExpression parameter) | |
{ | |
return new SpecificationParameterRebinder(parameter).Visit(expression); | |
} | |
protected override Expression VisitParameter(ParameterExpression p) | |
{ | |
return base.VisitParameter(specificationParameter); | |
} | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
namespace Sample.Repositories | |
{ | |
using System.Collections.Generic; | |
using System.Data.Entity; | |
using System.Linq; | |
using Specifications; | |
public class SpecificationRepository | |
{ | |
private readonly DbContext context; | |
public SpecificationRepository(DbContext context) | |
{ | |
this.context = context; | |
} | |
public ICollection<T> Find<T>(ISpecification<T> specification) where T : class | |
{ | |
var query = context.Set<T>().Where(specification.IsSatisifiedBy()); | |
return query.ToList(); | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment