Я использую Linq-to-SQL с Unity в шаблоне репозитория. Я пытаюсь добавить перехватчик для защиты объекта в методе репозитория [Securable]IQueryable<TEntity> List<TEntity>()
, который перехватывает вызов и возвращает только те объекты, на которые у пользователя есть права.
public class SecurableAttribute : HandlerAttribute
{...}
public class SecurableHandler : ICallHandler
{
...
IMethodReturn Invoke(IMethodInvocation input, GetNextHandlerDelegate getNext)
{
var message = getNext()(input, getNext);
var returnType = message.ReturnValue.GetType();
if (typeof(IQueryable).IsAssignableFrom(returnType))
{
var entityType = returnType.GetGenericArguments().Single();
var securableAttribute = entityType.GetAttribute<SecurableTypeAttribute>();
if(securableAttribute != null)
{
//Build expression to filter the list from the attribute and primary key of the entity
//Return the new IQueryable
}
}
return message;
}
}
Я построил выражение, но я не могу сделать message.ReturnValue.Where(expression)
, поскольку message.ReturnValue
это object
(message.ReturnValue
на самом деле System.Data.Linq.Table<TEntity>
, но я не хочу быть слишком привязанным к L2S ), и это во время выполнения, поэтому я не могу привести его обратно к универсальному и заменить message.ReturnValue
.
Или я попробовал
public interface ISecurable<TKey>
{
TKey SecurityId { get; }
}
на объекте, который немного меня блокирует, но я согласен с этим, если смогу отделить остальные аспекты безопасности. Это позволяет мне сделать следующее в IMethodReturn Invoke(IMethodInvocation input, GetNextHandlerDelegate getNext)
, где я строю вышеприведенное выражение:
if(typeof(ISecurableType).IsAssignableFrom(entityType))
{
var secured = ((IQueryable<ISecurable>)message.ReturnValue).Where(expression);
//Need to return secured as IQueryably<TEntity>
}
Теперь мне нужно привести secured
к IQueryable<ISecurable>
, но typeof(IQueryable<TEntity>).IsAssignableFrom(secured.GetType())
возвращает false, и выгрузка возвращаемого значения вызывает исключение, но, насколько я могу судить, оно работает с отложенным выполнением. (Кроме того, я не знаю TEntity во время разработки в SecurableHandler
, но я знаю отраженный тип - но я попытался использовать объявление класса, которое, как я знаю, находится в тестировании.)
Есть ли способ как-нибудь изменить возвращаемые результаты? Я застрял, нуждаясь в возвращении непатентованного файла, который я не знаю во время разработки, что делает это невозможным, но я также не могу изменить выражение (((IQueryable)message.ReturnType).Expression
объявлено как Expression Expression { get; }
).
Есть ли какой-нибудь блеск, который мог бы указать мне, как это работает?
tl; dr Необходимо вернуть IQueryable<TEntity>
во время выполнения от object
, то есть Table<TEntity> : IQueryable<TEntity>
с дополнительным .Where(expression)
.