supporting equality comparer :)

This commit is contained in:
David Lebée 2018-03-12 18:00:02 -05:00
parent 165cc15d0a
commit 9dd5d59b85
6 changed files with 52 additions and 15 deletions

View File

@ -8,10 +8,22 @@ using PoweredSoft.DynamicLinq;
namespace PoweredSoft.DynamicLinq.Test namespace PoweredSoft.DynamicLinq.Test
{ {
internal class TestStructure internal class TestStructureCompare : IEqualityComparer<TestStructure>
{ {
public long ClientId { get; set; } public bool Equals(TestStructure x, TestStructure y)
public decimal B { get; set; } {
return x?.ClientId == y?.ClientId;
}
public int GetHashCode(TestStructure obj)
{
return obj.ClientId;
}
}
internal class TestStructure
{
public int ClientId { get; set; }
} }
[TestClass] [TestClass]
@ -42,7 +54,22 @@ namespace PoweredSoft.DynamicLinq.Test
var dynamicSyntax3 = TestData.Sales var dynamicSyntax3 = TestData.Sales
.AsQueryable() .AsQueryable()
.GroupBy(t => t.UseType(typeof(TestStructure)).Path("ClientId").Path("NetSales", "B")); .GroupBy(t => t.UseType(typeof(TestStructure)).EqualityComparer(typeof(TestStructureCompare)).Path("ClientId"));
var tryAs = dynamicSyntax3 as EnumerableQuery<IGrouping<TestStructure, MockSale>>;
var list = tryAs.Select(t => new
{
Key = t.Key,
Data = t.ToList()
}).ToList();
var list2 = TestData.Sales.GroupBy(t => new TestStructure { ClientId = t.ClientId }, new TestStructureCompare()).Select(t => new
{
Key = t.Key,
Data = t.ToList()
}).ToList();
int i = 0;
/* /*
@ -57,8 +84,6 @@ namespace PoweredSoft.DynamicLinq.Test
Sales = t.ToList() Sales = t.ToList()
});*/ });*/
/* /*
.Select(t => .Select(t =>
{ {
@ -72,5 +97,10 @@ namespace PoweredSoft.DynamicLinq.Test
t.ToList("Sales"); t.ToList("Sales");
});*/ });*/
} }
private object compare(MockSale arg)
{
throw new NotImplementedException();
}
} }
} }

View File

@ -19,7 +19,7 @@ namespace PoweredSoft.DynamicLinq.Test
internal class MockSale internal class MockSale
{ {
public long Id { get; set; } public long Id { get; set; }
public long ClientId { get; set; } public int ClientId { get; set; }
public MockClient Client { get; set; } public MockClient Client { get; set; }
public decimal GrossSales { get; set; } public decimal GrossSales { get; set; }
public decimal NetSales { get; set; } public decimal NetSales { get; set; }

View File

@ -44,6 +44,7 @@ namespace PoweredSoft.DynamicLinq
internal static class Constants internal static class Constants
{ {
internal static readonly MethodInfo GroupByMethod = typeof(Queryable).GetMethods().First(t => t.Name == "GroupBy"); internal static readonly MethodInfo GroupByMethod = typeof(Queryable).GetMethods().First(t => t.Name == "GroupBy");
internal static readonly MethodInfo GroupByMethodWithEqualityComparer = typeof(Queryable).GetMethods().First(t => t.Name == "GroupBy" && t.GetParameters().Any(t2 => t2.Name == "comparer"));
internal static readonly MethodInfo StringEqualWithComparisation = typeof(string).GetMethod("Equals", new Type[] { typeof(string), typeof(StringComparison) }); internal static readonly MethodInfo StringEqualWithComparisation = typeof(string).GetMethod("Equals", new Type[] { typeof(string), typeof(StringComparison) });
internal static readonly MethodInfo ContainsMethod = typeof(string).GetMethod("Contains"); internal static readonly MethodInfo ContainsMethod = typeof(string).GetMethod("Contains");
internal static readonly MethodInfo StartsWithMethod = typeof(string).GetMethod("StartsWith", new Type[] { typeof(string) }); internal static readonly MethodInfo StartsWithMethod = typeof(string).GetMethod("StartsWith", new Type[] { typeof(string) });

View File

@ -86,7 +86,7 @@ namespace PoweredSoft.DynamicLinq
if (groupBuilder.Empty) if (groupBuilder.Empty)
throw new Exception("No group specified, please specify at least one group"); throw new Exception("No group specified, please specify at least one group");
return QueryableHelpers.GroupBy(query, type, groupBuilder.Parts, groupBuilder.Type); return QueryableHelpers.GroupBy(query, type, groupBuilder.Parts, groupBuilder.Type, groupBuilder.EqualityComparerType);
} }
} }
} }

View File

@ -10,6 +10,7 @@ namespace PoweredSoft.DynamicLinq.Fluent
public List<(string path, string propertyName)> Parts { get; set; } = new List<(string path, string propertyName)>(); public List<(string path, string propertyName)> Parts { get; set; } = new List<(string path, string propertyName)>();
public Type Type { get; set; } public Type Type { get; set; }
public bool Empty => !Parts.Any(); public bool Empty => !Parts.Any();
public Type EqualityComparerType { get; set; }
public GroupBuilder Path(string path, string propertyName = null) public GroupBuilder Path(string path, string propertyName = null)
{ {
@ -37,5 +38,11 @@ namespace PoweredSoft.DynamicLinq.Fluent
Type = type; Type = type;
return this; return this;
} }
public GroupBuilder EqualityComparer(Type type)
{
EqualityComparerType = type;
return this;
}
} }
} }

View File

@ -77,7 +77,7 @@ namespace PoweredSoft.DynamicLinq.Helpers
return ret; return ret;
} }
public static IQueryable GroupBy(IQueryable query, Type type, List<(string path, string propertyName)> parts, Type groupToType = null) public static IQueryable GroupBy(IQueryable query, Type type, List<(string path, string propertyName)> parts, Type groupToType = null, Type equalityCompareType = null)
{ {
// EXPRESSION // EXPRESSION
var parameter = Expression.Parameter(type, "t"); var parameter = Expression.Parameter(type, "t");
@ -93,8 +93,7 @@ namespace PoweredSoft.DynamicLinq.Helpers
partExpressions.Add((partExpression, part.propertyName)); partExpressions.Add((partExpression, part.propertyName));
}); });
var anonymousType = groupToType ?? TypeHelpers.CreateSimpleAnonymousType(fields); var keyType = groupToType ?? TypeHelpers.CreateSimpleAnonymousType(fields);
/* /*
var constructorTypes = fields.Select(t => t.type).ToArray(); var constructorTypes = fields.Select(t => t.type).ToArray();
@ -105,12 +104,12 @@ namespace PoweredSoft.DynamicLinq.Helpers
var groupByExpression = Expression.Call(genericMethod, query.Expression, lambda); var groupByExpression = Expression.Call(genericMethod, query.Expression, lambda);
var result = query.Provider.CreateQuery(groupByExpression);*/ var result = query.Provider.CreateQuery(groupByExpression);*/
var ctor = Expression.New(anonymousType); var ctor = Expression.New(keyType);
var bindings = partExpressions.Select(partExpression => Expression.Bind(anonymousType.GetProperty(partExpression.propertyName), partExpression.expression)).ToList(); var bindings = partExpressions.Select(partExpression => Expression.Bind(keyType.GetProperty(partExpression.propertyName), partExpression.expression)).ToList();
var mi = Expression.MemberInit(ctor, bindings.ToArray()); var mi = Expression.MemberInit(ctor, bindings.ToArray());
var lambda = Expression.Lambda(mi, parameter); var lambda = Expression.Lambda(mi, parameter);
var genericMethod = Constants.GroupByMethod.MakeGenericMethod(type, anonymousType); var genericMethod = equalityCompareType == null ? Constants.GroupByMethod.MakeGenericMethod(type, keyType) : Constants.GroupByMethodWithEqualityComparer.MakeGenericMethod(type, keyType); //, Activator.CreateInstance(equalityCompareType));
var groupByExpression = Expression.Call(genericMethod, query.Expression, lambda); var groupByExpression = equalityCompareType == null ? Expression.Call(genericMethod, query.Expression, lambda) : Expression.Call(genericMethod, query.Expression, lambda, Expression.New(equalityCompareType));
var result = query.Provider.CreateQuery(groupByExpression); var result = query.Provider.CreateQuery(groupByExpression);
return result; return result;
} }