This commit is contained in:
Biarity 2018-07-04 13:06:37 +10:00
parent 254eec529e
commit b92df9833d
3 changed files with 39 additions and 32 deletions

View File

@ -18,7 +18,7 @@ namespace Sieve.Extensions
/// <exception cref="AmbiguousMatchException"/> /// <exception cref="AmbiguousMatchException"/>
public static MethodInfo GetMethodExt(this Type thisType, public static MethodInfo GetMethodExt(this Type thisType,
string name, string name,
params Type[] parameterTypes) Type firstType)
{ {
return GetMethodExt(thisType, return GetMethodExt(thisType,
name, name,
@ -27,7 +27,7 @@ namespace Sieve.Extensions
| BindingFlags.Public | BindingFlags.Public
| BindingFlags.NonPublic | BindingFlags.NonPublic
| BindingFlags.FlattenHierarchy, | BindingFlags.FlattenHierarchy,
parameterTypes); firstType);
} }
/// <summary> /// <summary>
@ -39,12 +39,12 @@ namespace Sieve.Extensions
public static MethodInfo GetMethodExt(this Type thisType, public static MethodInfo GetMethodExt(this Type thisType,
string name, string name,
BindingFlags bindingFlags, BindingFlags bindingFlags,
params Type[] parameterTypes) Type firstType)
{ {
MethodInfo matchingMethod = null; MethodInfo matchingMethod = null;
// Check all methods with the specified name, including in base classes // Check all methods with the specified name, including in base classes
GetMethodExt(ref matchingMethod, thisType, name, bindingFlags, parameterTypes); GetMethodExt(ref matchingMethod, thisType, name, bindingFlags, firstType);
// If we're searching an interface, we have to manually search base interfaces // If we're searching an interface, we have to manually search base interfaces
if (matchingMethod == null && thisType.IsInterface) if (matchingMethod == null && thisType.IsInterface)
@ -54,7 +54,7 @@ namespace Sieve.Extensions
interfaceType, interfaceType,
name, name,
bindingFlags, bindingFlags,
parameterTypes); firstType);
} }
return matchingMethod; return matchingMethod;
@ -64,7 +64,7 @@ namespace Sieve.Extensions
Type type, Type type,
string name, string name,
BindingFlags bindingFlags, BindingFlags bindingFlags,
params Type[] parameterTypes) Type firstType)
{ {
// Check all methods with the specified name, including in base classes // Check all methods with the specified name, including in base classes
foreach (MethodInfo methodInfo in type.GetMember(name, foreach (MethodInfo methodInfo in type.GetMember(name,
@ -74,23 +74,14 @@ namespace Sieve.Extensions
// Check that the parameter counts and types match, // Check that the parameter counts and types match,
// with 'loose' matching on generic parameters // with 'loose' matching on generic parameters
ParameterInfo[] parameterInfos = methodInfo.GetParameters(); ParameterInfo[] parameterInfos = methodInfo.GetParameters();
if (parameterInfos.Length == parameterTypes.Length)
if (parameterInfos[0].ParameterType.IsSimilarType(firstType))
{ {
int i = 0; if (matchingMethod == null)
for (; i < parameterInfos.Length; ++i) matchingMethod = methodInfo;
{ else
if (!parameterInfos[i].ParameterType throw new AmbiguousMatchException(
.IsSimilarType(parameterTypes[i])) "More than one matching method found!");
break;
}
if (i == parameterInfos.Length)
{
if (matchingMethod == null)
matchingMethod = methodInfo;
else
throw new AmbiguousMatchException(
"More than one matching method found!");
}
} }
} }
} }

View File

@ -211,12 +211,12 @@ namespace Sieve.Services
} }
else else
{ {
var parameters = new object[] { result = ApplyCustomMethod(result, filterTermName, _customFilterMethods,
new object[] {
result, result,
filterTerm.Operator, filterTerm.Operator,
filterTerm.Value filterTerm.Value
}; }, dataForCustomMethods);
result = ApplyCustomMethod(result, filterTermName, _customFilterMethods, parameters, dataForCustomMethods);
} }
} }
@ -347,20 +347,23 @@ namespace Sieve.Services
bool canSortRequired, bool canSortRequired,
bool canFilterRequired, bool canFilterRequired,
string name, string name,
bool isCaseSensitive) => Array.Find(typeof(TEntity).GetProperties(), p => bool isCaseSensitive)
{ {
return p.GetCustomAttribute(typeof(SieveAttribute)) is SieveAttribute sieveAttribute return Array.Find(typeof(TEntity).GetProperties(), p =>
{
return p.GetCustomAttribute(typeof(SieveAttribute)) is SieveAttribute sieveAttribute
&& (canSortRequired ? sieveAttribute.CanSort : true) && (canSortRequired ? sieveAttribute.CanSort : true)
&& (canFilterRequired ? sieveAttribute.CanFilter : true) && (canFilterRequired ? sieveAttribute.CanFilter : true)
&& ((sieveAttribute.Name ?? p.Name).Equals(name, isCaseSensitive ? StringComparison.Ordinal : StringComparison.OrdinalIgnoreCase)); && ((sieveAttribute.Name ?? p.Name).Equals(name, isCaseSensitive ? StringComparison.Ordinal : StringComparison.OrdinalIgnoreCase));
}); });
}
private IQueryable<TEntity> ApplyCustomMethod<TEntity>(IQueryable<TEntity> result, string name, object parent, object[] parameters, object[] optionalParameters = null) private IQueryable<TEntity> ApplyCustomMethod<TEntity>(IQueryable<TEntity> result, string name, object parent, object[] parameters, object[] optionalParameters = null)
{ {
var customMethod = parent?.GetType() var customMethod = parent?.GetType()
.GetMethodExt(name, .GetMethodExt(name,
_options.Value.CaseSensitive ? BindingFlags.Default : BindingFlags.IgnoreCase | BindingFlags.Public | BindingFlags.Instance, _options.Value.CaseSensitive ? BindingFlags.Default : BindingFlags.IgnoreCase | BindingFlags.Public | BindingFlags.Instance,
new Type[] { typeof(IQueryable<TEntity>), typeof(string), typeof(string) }); typeof(IQueryable<TEntity>));
if (customMethod != null) if (customMethod != null)
{ {

View File

@ -224,6 +224,19 @@ namespace SieveUnitTests
Assert.AreEqual(2, commentResult.Count()); Assert.AreEqual(2, commentResult.Count());
} }
[TestMethod]
public void CustomSortsWork()
{
var model = new SieveModel()
{
Sorts = "Popularity",
};
var result = _processor.Apply(model, _posts);
Assert.IsFalse(result.First().Id == 0);
}
[TestMethod] [TestMethod]
public void MethodNotFoundExceptionWork() public void MethodNotFoundExceptionWork()
{ {