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

View File

@ -180,7 +180,7 @@ namespace Sieve.Services
if (property != null)
{
var converter = TypeDescriptor.GetConverter(property.PropertyType);
dynamic constantVal = converter.CanConvertFrom(typeof(string))
? converter.ConvertFrom(filterTerm.Value)
: Convert.ChangeType(filterTerm.Value, property.PropertyType);
@ -211,13 +211,13 @@ namespace Sieve.Services
}
else
{
var parameters = new object[] {
result = ApplyCustomMethod(result, filterTermName, _customFilterMethods,
new object[] {
result,
filterTerm.Operator,
filterTerm.Value
};
result = ApplyCustomMethod(result, filterTermName, _customFilterMethods, parameters, dataForCustomMethods);
}, dataForCustomMethods);
}
}
if (outerExpression == null)
@ -347,20 +347,23 @@ namespace Sieve.Services
bool canSortRequired,
bool canFilterRequired,
string name,
bool isCaseSensitive) => Array.Find(typeof(TEntity).GetProperties(), p =>
{
return p.GetCustomAttribute(typeof(SieveAttribute)) is SieveAttribute sieveAttribute
bool isCaseSensitive)
{
return Array.Find(typeof(TEntity).GetProperties(), p =>
{
return p.GetCustomAttribute(typeof(SieveAttribute)) is SieveAttribute sieveAttribute
&& (canSortRequired ? sieveAttribute.CanSort : true)
&& (canFilterRequired ? sieveAttribute.CanFilter : true)
&& ((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)
{
var customMethod = parent?.GetType()
.GetMethodExt(name,
_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)
{

View File

@ -224,6 +224,19 @@ namespace SieveUnitTests
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]
public void MethodNotFoundExceptionWork()
{