2011-01-13 51 views
2

在我的域模型中,我有一个基类实体类,所有类都从中派生出来。
我希望能够根据当前用户的权限动态创建过滤器。
例如 - 对于Employee类,我会定义员工可以看到他自己和他的部门。
我的方法会去是这样的:
动态确定要调用哪种静态方法

public static IQueryable<Employee> CreateLinqFilter(IQueryable<Employee> query, User user) 
    { 
     return query.Where(e => e.Id == user.Id || e.Department.Manager.Id == user.Id); 
    } 

,然后在我的仓库基类,我想动态确定的类型和调用正确的方法CreateLinqFilter:

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... 
    } 

迄今为止唯一的解决方案是很多if-else块,这些块很难看。
任何人都有更好的主意?
感谢
的Jhonny

+0

我几乎可以肯定地错过了这里的东西,但为什么你不只是在你的实体类声明一个“CreateLinqFilter”,然后而不是所有这些relkin类型的东西,或者只是如果声明不能只是调用“entity.CreateLinqFilter并且它只是把它称为正确的东西?正如我所说,我可能错过了一些东西,我想知道什么.-) – Chris 2011-01-13 15:15:35

+0

@Chris,因为CreateLinqFilter函数对实体的* Collections *有效,它很漂亮在一个单一的实体环境中没有意义;函数实际上是静态的... – 2011-01-16 13:11:54

+0

啊,是的,这是有道理的,我偶尔也会遇到困难,我的脑袋在仿制药和他们需要居住的地方:) – Chris 2011-01-17 10:38:44

回答

1

试着这么做:

return (IQueryable)typeof(T).GetMethod("CreateLinqFilter").Invoke(null, new object[]{query, user}); 

这使用反射来找到在运行时的方法;如果这太慢,您可能需要考虑在某处缓存GetMethod的结果。请注意,此方法不限于静态方法;用指向T类型对象的指针替换null,并且您也可以在普通实例方法上使用它。

欲了解更多信息,请参阅MSDN documentation for the reflection classes;你可以在documentation for Invoke找到一个很好的例子。

0

在C#4.0中,你可以使用一个动态= T T,如果没有,也许你只能使用第一个答案

0

嗯,首先,不要用大量的if..else块,使用开关。

0

这是一个非常好的解决方案,IMO只是在派生的资源库类中调用方法,而不是在基础资源库中调用。那么你没有问题,因为派生类知道它在查询什么,所以EmployeesRepository将显式调用Employee.GetFilter。