public
Last active

Convention Approach to Creating Filters with Nhibernate

  • Download Gist
BasicFilter.cs
C#
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25
public class BasicFilter
{
public Guid? ClientGroupId { get; set; }
 
[LikeQueryFilter(ComponentModel = typeof (Address))]
public string AddressCity { get; set; }
 
[QueryFilter(ComponentModel = typeof (Address))]
public string AddressState { get; set; }
 
[QueryFilter(ComponentModel = typeof (Address))]
public string AddressZip { get; set; }
 
[LikeQueryFilter(ComponentModel = typeof (Address))]
public string AddressLine1 { get; set; }
 
[LikeQueryFilter(ComponentModel = typeof (Address))]
public string AddressLine2 { get; set; }
 
public int? ClientId { get; set; }
 
public long? PropertyId { get; set; }
public Guid AssignedToUserId { get; set; }
}
FilterQueryBuilder.cs
C#
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42
 
public class FilterQueryBuilder
{
public IEnumerable<ICriterion> CreateFilter(object filter, Type objectToFilter)
{
var criterion = new List<ICriterion>();
var props = filter.GetType().GetProperties();
foreach (var pi in props)
{
var val = pi.GetValue(filter, null);
if (ShouldNotAddToFilter(pi, val)) continue;
var queryAttribute = (QueryFilterAttribute) pi.GetCustomAttributes(typeof (QueryFilterAttribute), true).FirstOrDefault();
if (queryAttribute == null)
{
criterion.Add(new SimpleExpression(pi.Name, val, "="));
continue;
}
var name_to_return = GetNameFromAttribute(queryAttribute, pi, objectToFilter);
criterion.Add(queryAttribute.GetCriteria(name_to_return, val));
}
return criterion;
}
 
static bool ShouldNotAddToFilter(PropertyInfo pi, object propertyValue)
{
if (propertyValue == null) return true;
if(pi.GetCustomAttributes(false).Any(x=>x is NotAFilter)) return true;
return pi.PropertyType == typeof (Guid) && (Guid) propertyValue == Guid.Empty;
}
 
static string GetNameFromAttribute(QueryFilterAttribute queryAttribute, PropertyInfo filterProperty, Type objectToFilter)
{
if (queryAttribute.ComponentModel == null) return filterProperty.Name;
var filter_property_name = filterProperty.Name;
 
var filtered_type_property_name = objectToFilter.GetProperties()
.Where(info => info.PropertyType == queryAttribute.ComponentModel && filter_property_name.StartsWith(info.Name)).First().Name;
 
var component_property_name = filterProperty.Name.Replace(filtered_type_property_name, "");
return filtered_type_property_name + "." + component_property_name;
}
}
QueryFilterAttributes.cs
C#
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60
public class NotAFilter: Attribute
{
}
 
public class FilterGroup : Attribute
{
public FilterGroup(string displayName)
{
DisplayName = displayName;
}
 
public FilterGroup()
{
}
 
public string DisplayName { get; set; }
}
 
public class QueryFilterAttribute : Attribute
{
public virtual ICriterion GetCriteria(string propertyName, object val)
{
return Restrictions.Eq(propertyName, val);
}
public Type ComponentModel { get; set; }
}
 
public class LikeQueryFilterAttribute : QueryFilterAttribute
{
public override ICriterion GetCriteria(string propertyName, object val)
{
return new LikeExpression(propertyName, val.ToString(), MatchMode.Anywhere);
}
}
 
public class DayPrecisionDateQueryFilterAttribute : QueryFilterAttribute
{
public override ICriterion GetCriteria(string propertyName, object val)
{
var value = (DateTimeOffset) val;
return new BetweenExpression(propertyName, value, value.AddDays(1).AddMilliseconds(-1));
}
}
 
public class IgnoreFilterAttribute : QueryFilterAttribute
{
public override ICriterion GetCriteria(string propertyName, object val)
{
return new NotNullExpression(propertyName);
}
}
public class GreaterThanFilterAttribute : QueryFilterAttribute
{
public override ICriterion GetCriteria(string propertyName, object val)
{
return Restrictions.Gt(propertyName, val);
}
}

Please sign in to comment on this gist.

Something went wrong with that request. Please try again.