[ActiveRecord]
public class Entity : ActiveRecordBase<Entity>
{
private int id;
private string name;
private string entityDesc;
private string internalName;
[PrimaryKey]
public int Id
{
get { return id; }
set { id = value; }
}
[Searchable][Property]
public string Name
{
get { return name; }
set { name = value; }
}
[Searchable(FriendlyName = "Description")][Property]
public string EntityDesc
{
get { return entityDesc; }
set { entityDesc = value; }
}
[Property]
public string InternalName
{
get { return internalName; }
set { internalName = value; }
}
}The Searchable takes an optional parameter, FriendlyName that allows to specify a localized or other, more user-friendly name. The attribute can be applied to both properties and relations. If applied to a relation attribute (BelongsTo, HasMany, HasAndBelongsToMany etc.) the properties tagged in that type will be added to the search as well. Then there is a SearchMediator, which will create a NHibernate Criteria Query that will check for every search term whether it can be parsed by the datatype of a tagged property and adds it to the query if this is the case. The code below sketches how the query could be created:
public static T[] Search(string text)
{
string[] words = text.Split();
DetachedCriteria criteria = DetachedCriteria.For<T>();
foreach (string word in words)
{
Disjunction group = Expression.Disjunction();
foreach (PropertyInfo info in typeof (T).GetProperties())
{
if (info.GetCustomAttributes(typeof (SearchableAttribute), true).Length > 0)
group.Add(Expression.Like(info.Name, word, MatchMode.Anywhere));
}
criteria.Add(group);
}
return ActiveRecordMediator<T>.FindAll(criteria);
}
This can be extended by many means. Examples include:
- Allowing propertyName:searchTerm to narrow search to a specific property by its name or friendly name.
- Allowing other operators than the colon like price>10.00 or name!Foo
- Add globbing to specify whether exact matches or all matches should be found
- Specify the MatchMode behavior for string properties as part of SearchableAttribute
Using that mechanism, I can add searching to almost any entity similar to validation. What do you think, would such a Search component benefit the Castle Framework?
That is only some thoughts. I didn't start implementing anything yet. However, anyone interested in helping is welcome, of course.