динамически определять, какой статический метод вызывать - PullRequest
2 голосов
/ 13 января 2011

В моей доменной модели у меня есть базовый класс сущности, из которого все классы происходят.
Я бы хотел иметь возможность динамически создавать фильтры на основе разрешений текущего пользователя.
Например, для класса 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, которые довольно неприглядны.
кто-нибудь есть идеи получше?
спасибо
Джонни

Ответы [ 4 ]

1 голос
/ 13 января 2011

Попробуйте что-то вроде:

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

Это использует отражение, чтобы найти метод во время выполнения; если это слишком медленно, вы можете рассмотреть кэширование результата GetMethod где-нибудь. Обратите внимание, что этот метод не ограничен статическим методом; замените null указателем на объект типа T, и вы также можете использовать его в обычных методах экземпляра.

Для получения дополнительной информации обратитесь к документации MSDN для классов отражения ; Вы можете найти хороший пример в документации для Invoke .

0 голосов
/ 26 августа 2011

Действительно хорошее решение, IMO просто вызывает метод в производном классе репозитория, а не в вашем базовом репозитории.Тогда у вас нет проблем, потому что производный класс знает, что он запрашивает, поэтому EmployeesRepository явно вызовет Employee.GetFilter.

0 голосов
/ 14 января 2011

Ну, во-первых, не используйте много блоков if..else, используйте переключатель.

0 голосов
/ 13 января 2011

в c # 4.0, вы можете использовать динамический a = T t, если нет, может быть, вы можете использовать только первый ответ

...