Skip to content

Instantly share code, notes, and snippets.

@jstemerdink
Last active September 29, 2016 13:20
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save jstemerdink/4af1bd14f06aa7f2ee6f to your computer and use it in GitHub Desktop.
Save jstemerdink/4af1bd14f06aa7f2ee6f to your computer and use it in GitHub Desktop.
Use an attribute to create facets for an EPiServer Find query
[Facet(1, FacetType.TermsFacetFor)]
public virtual string TermsFacetExample { get; set; }
IClient searchManager = Client.CreateFromConfig();
ITypeSearch<StandardPage> queryTest = searchManager.Search<StandardPage>().For("test");
queryTest = queryTest.AddFacets();
IContentResult<StandardPage> results = queryTest.GetContentResult();
/// <summary>
/// Class FacetAttribute. This class cannot be inherited.
/// </summary>
[AttributeUsage(AttributeTargets.Property)]
public sealed class FacetAttribute : Attribute
{
/// <summary>
/// Initializes a new instance of the <see cref="FacetAttribute"/> class.
/// </summary>
/// <param name="index">The index.</param>
/// <param name="facetType">Type of the facet.</param>
public FacetAttribute(int index, FacetType facetType)
{
this.Index = index;
this.FacetType = facetType;
}
/// <summary>
/// Initializes a new instance of the <see cref="FacetAttribute"/> class.
/// </summary>
/// <param name="index">The index.</param>
public FacetAttribute(int index)
{
this.Index = index;
this.FacetType = FacetType.TermsFacetFor;
}
/// <summary>
/// Initializes a new instance of the <see cref="FacetAttribute"/> class.
/// </summary>
public FacetAttribute()
{
this.Index = 0;
this.FacetType = FacetType.TermsFacetFor;
}
#region Public Properties
/// <summary>
/// Gets the index.
/// </summary>
/// <value>The index.</value>
public int Index { get; }
/// <summary>
/// Gets the type of the facet.
/// </summary>
/// <value>The type of the facet.</value>
public FacetType FacetType { get; }
/// <summary>
/// Gets a value indicating whether the property is used as a facet in EPiServer Find.
/// </summary>
/// <value><c>true</c> if [used as a facet in EPiServer Find]; otherwise, <c>false</c>.</value>
public static bool Facet
{
get
{
return true;
}
}
#endregion
}
/// <summary>
/// Enum FacetType
/// </summary>
public enum FacetType
{
TermsFacetForWordsIn,
TermsFacetFor
}
/// <summary>
/// Class FindExtensions.
/// </summary>
public static class FindExtensions
{
/// <summary>
/// Adds facets to a Find query base on an attribute.
/// </summary>
/// <typeparam name="T">The content type to add the facets for.</typeparam>
/// <param name="query">The query.</param>
/// <returns>ITypeSearch&lt;T&gt;.</returns>
public static ITypeSearch<T> AddFacets<T>(this ITypeSearch<T> query) where T : IContent
{
foreach (PropertyInfo propertyInfo in GetPropertiesSortedByIndex<T>())
{
FacetAttribute facetAttribute = Attribute.GetCustomAttribute(propertyInfo, typeof(FacetAttribute)) as FacetAttribute;
if (facetAttribute == null)
{
continue;
}
ParameterExpression expParam = Expression.Parameter(typeof(T), "x");
MemberExpression expProp = Expression.Property(expParam, propertyInfo);
Type delegateType = typeof(Func<,>).MakeGenericType(typeof(T), propertyInfo.PropertyType);
dynamic expression = Expression.Lambda(delegateType, expProp, expParam);
try
{
switch (facetAttribute.FacetType)
{
case FacetType.TermsFacetFor:
query = TypeSearchExtensions.TermsFacetFor(query, expression);
break;
case FacetType.TermsFacetForWordsIn:
query = TypeSearchExtensions.TermsFacetForWordsIn(query, expression);
break;
default:
query = TypeSearchExtensions.TermsFacetFor(query, expression);
break;
}
}
catch (Exception)
{
}
}
return query;
}
/// <summary>
/// Gets the properties that has the FacetAttribute sorted by the index.
/// </summary>
/// <typeparam name="T">The type to get the properties for.</typeparam>
/// <returns>IEnumerable&lt;PropertyInfo&gt;.</returns>
private static IEnumerable<PropertyInfo> GetPropertiesSortedByIndex<T>() where T : IContent
{
PropertyInfo[] allProperties = typeof(T)
.GetProperties()
.Where(HasAttribute<FacetAttribute>)
.Select(x => new
{
Property = x,
Attribute = (FacetAttribute)Attribute.GetCustomAttribute(x, typeof(FacetAttribute), true)
})
.OrderBy(x => x.Attribute != null ? x.Attribute.Index : -1)
.Select(x => x.Property)
.ToArray();
return allProperties;
}
/// <summary>
/// Determines whether the specified property has the specified attribute.
/// </summary>
/// <typeparam name="T">The attribute type.</typeparam>
/// <param name="propertyInfo">The propertyInfo.</param>
/// <returns><c>true</c> if the specified self has attribute; otherwise, <c>false</c>.</returns>
private static bool HasAttribute<T>(PropertyInfo propertyInfo) where T : Attribute
{
T attr = default(T);
try
{
attr = (T)Attribute.GetCustomAttribute(propertyInfo, typeof(T));
}
catch (Exception)
{
}
return attr != null;
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment