Ninject interception attribute with parameters passed to interceptor?

1.7k views Asked by At

I have interception working currently (very simplistically) with the following code:

(see question at bottom)

My Interceptor:

public interface IAuthorizationInterceptor : IInterceptor { }
public class AuthorizationInterceptor : IAuthorizationInterceptor
{


    public IParameter[] AttributeParameters { get; private set; }


    // This doesnt work currently... paramters has no values
    public AuthorizationInterceptor(IParameter[] parameters) {
        AttributeParameters = parameters;
    }

    public void Intercept(IInvocation invocation) {
        // I have also tried to get the attributes like this
        // which also returns nothing.
        var attr = invocation.Request.Method.GetCustomAttributes(true);


        try {
            BeforeInvoke(invocation);
        } catch (AccessViolationException ex) {

        } catch (Exception ex) {
            throw;
        }
        // Continue method and/or processing additional attributes
        invocation.Proceed();
        AfterInvoke(invocation);
    }


    protected void BeforeInvoke(IInvocation invocation) {

        // Enumerate parameters of method call
        foreach (var arg in invocation.Request.Arguments) {
            // Just a test to see if I can get arguments
        }

        //TODO: Replace with call to auth system code.
        bool isAuthorized = true;

        if (isAuthorized == true) {
            // Do stuff               
        }
        else {
            throw new AccessViolationException("Failed");
        }             
    }

    protected  void AfterInvoke(IInvocation invocation) {


    }
}

My Attribute:

public class AuthorizeAttribute : InterceptAttribute
{
    public string[] AttributeParameters { get; private set; }

    public AuthorizeAttribute(params string[] parameters) {
        AttributeParameters = parameters;
    }

    public override IInterceptor CreateInterceptor(IProxyRequest request) {
        var param = new List<Parameter>();
        foreach(string p in AttributeParameters) {
            param.Add( new Parameter(p, p, false));
        }
        // Here I have tried passing ConstructorArgument(s) but the result
        // in the inteceptor constructor is the same. 
        return request.Context.Kernel.Get<IAuthorizationInterceptor>(param.ToArray());
    }
}

Applied to a method:

[Authorize("test")]
public virtual Result<Vault> Vault(DateTime date, bool LiveMode = true, int? SnapshotId = null)
{
        ...
}

This works, and I am able to pass additional parameters through the attribute like this:

[Authorize("test")]

If you'll noticed in my attribute I am grabbing some parameters from the attribute, which I am able to access in the attribute class, but I am unable to pass those to the Interceptor. I have tried using the ConstructorArgument in the Kernel.Get<>() call, which doesnt throw an error, but the AuthorizationInterceptor constructor doesnt get any values from ninject. I have also tried GetCustomAttributes() as you can see in the code sample but this also returns nothing. From looking at other similar posts like this (Ninject Interception 3.0 Interface proxy by method attributes) that seems to be the correct way, but it doesn't work. Any ideas?

1

There are 1 answers

0
Brandon On BEST ANSWER

I was able to get something working by creating an initialization method on the interceptor. I don't really like it, because it ties me to the specific implementation of AuthorizationInterceptor, but it gets the job done (damn deadlines lol). I would still like to know if there is a better way to do this, so I am not going to mark my own answer in hopes that somebody comes along with a better way of doing this.

I modified the attribute as follows:

    public override IInterceptor CreateInterceptor(IProxyRequest request) {
        AuthorizationInterceptor attr = (AuthorizationInterceptor)request.Context.Kernel.Get<IAuthorizationInterceptor>();
        attr.Init(AttributeParameters);
        return attr;
    }

And created an Init method on the the interceptor:

    public void Init(params string[] parameters) {
        AttributeParameters = parameters;
    }