简体   繁体   中英

determine dynamically which static method to invoke

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 .

在c#4.0中,您可以使用动态a = T t,否则,也许只能使用第一个答案

好吧,首先,不要使用很多if..else块,而要使用开关。

The really good solution, IMO is simply calling the method in the derived repository class and not in your base repository. Then you have no problem because the derived class knows what it is querying, so EmployeesRepository will explicitly call Employee.GetFilter.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM