Note that there are some explanatory texts on larger screens.

plurals
  1. POLinq to SQL with Unity Interception
    text
    copied!<p>I am using Linq-to-SQL with Unity in a Repository pattern. I am trying to add an interceptor for object security on the repository method <code>[Securable]IQueryable&lt;TEntity&gt; List&lt;TEntity&gt;()</code> that intercepts the call and returns only the entities that the user has rights to. </p> <pre><code>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&lt;SecurableTypeAttribute&gt;(); if(securableAttribute != null) { //Build expression to filter the list from the attribute and primary key of the entity //Return the new IQueryable } } return message; } } </code></pre> <p>I have built an expression, but I can't do <code>message.ReturnValue.Where(expression)</code> since the <code>message.ReturnValue</code> is <code>object</code> (<code>message.ReturnValue</code> is actually a <code>System.Data.Linq.Table&lt;TEntity&gt;</code>, but I don't want to be too tied to L2S), and it is at runtime so I can't cast it back to a generic and replace <code>message.ReturnValue</code>. </p> <p>Alternatively, I tried</p> <pre><code>public interface ISecurable&lt;TKey&gt; { TKey SecurityId { get; } } </code></pre> <p>on the entity, which locks me in a bit, but I am OK with that if I could separate the remaining security aspects. This allows me to do the following in <code>IMethodReturn Invoke(IMethodInvocation input, GetNextHandlerDelegate getNext)</code> where I build the expression above:</p> <pre><code>if(typeof(ISecurableType).IsAssignableFrom(entityType)) { var secured = ((IQueryable&lt;ISecurable&gt;)message.ReturnValue).Where(expression); //Need to return secured as IQueryably&lt;TEntity&gt; } </code></pre> <p>I now have to cast <code>secured</code> to <code>IQueryable&lt;ISecurable&gt;</code> but <code>typeof(IQueryable&lt;TEntity&gt;).IsAssignableFrom(secured.GetType())</code> returns false, and swapping out the return value throws an exception, but it does seem to work with delayed execution as far as I can tell. (Also, I don't know TEntity at design time in <code>SecurableHandler</code>, but I do know the reflected type - but I have tried using the class declaration that I know it is in testing.)</p> <p>Is there any way to modify the return results somehow? I am stuck needing to return a generic that I don't know at design time, thus making that impossible, but I also can't modify the expression (<code>((IQueryable)message.ReturnType).Expression</code> is declared as <code>Expression Expression { get; }</code>).</p> <p>Is there any brilliance out there that could point me in a way that works?</p> <p>tl;dr Need to return an <code>IQueryable&lt;TEntity&gt;</code> at runtime from an <code>object</code> that is a <code>Table&lt;TEntity&gt; : IQueryable&lt;TEntity&gt;</code> with an additional <code>.Where(expression)</code>.</p>
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload