In my domain model, I have a base entity class from which all classes derive.
I'd like to be able to create filters dynamically based on current user's permissions.
For example- For the Employee class, I would define that an employee can see himself, and his department.
My method would go something like this:
public static IQueryable<Employee> CreateLinqFilter(IQueryable<Employee> query, User user)
{
return query.Where(e => e.Id == user.Id || e.Department.Manager.Id == user.Id);
}
and then, in my repository base class, I'd like to determine the type dynamically and call the correct CreateLinqFilter method:
protected IQueryable CreateLinq<T>(User user)
{
var query = Session.Linq<T>();
Type t = typeof(T);
//if not an entity- do not perform filter
if (!t.IsAssignableFrom(typeof(Entity)))
{
return query;
}
//now we know that T is a sub-class of Entity.
return CreateLinqFilter<T>(query,user);
}
protected IQueryable CreateLinqFilter<T>(IQueryable<T> query, User user)
//the following line won't compile:
//where T: Entity
{
//i'd like to be able to do:
//T.CreateFilter(query);
//instead, I have to do this?
if (typeof(T) == Employee)
{
return Employee.CreateLinqFilter(query,user);
}
if (typeof(T) == Department)
{
return Department.CreateLinqFilter(query,user);
}
//etc...
}
The only solution I've got so far is lots of if-else blocks, which are quite unsightly.
anyone got a better idea?
thanks
Jhonny
Try something like:
return (IQueryable)typeof(T).GetMethod("CreateLinqFilter").Invoke(null, new object[]{query, user});
This uses reflection to find the method at runtime; if this is too slow you may want to consider caching the result of GetMethod
somewhere. Note that this method is not restricted to static method; replace the null with a pointer to an object of type T and you can use it on normal instance methods as well.
For more information, consult the MSDN documentation for the reflection classes; you can find a nice example in the documentation for Invoke.