Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Return exception from proxy

I'm using the heavily-undocumented Castle dynamic-proxy system. I've managed to make it do almost everything I want, except for one thing: How do you make a proxied method throw an exception instead of returning a value?

public sealed class MyInterceptor : IInterceptor
{
  public void Intercept(IInvocation invocation)
  {
    if (CheckArgs(invocation.Arguments))
    {
      invocation.ReturnValue = DoRealWork(invocation.Arguments);
    }
    else
    {
      invocation.Exception = new InvalidOperationException(); // How?
    }
  }
}
like image 375
MathematicalOrchid Avatar asked Nov 01 '22 10:11

MathematicalOrchid


1 Answers

From the point of view of the proxied object the interceptor is not visible; it simply calls its own virtual method, and DynamicProxy invokes the correct interceptor methods before returning the ReturnValue to the caller.

So if you want to throw an exception just throw it from the interceptor:

if (CheckArgs(invocation.Arguments))
{
  invocation.ReturnValue = DoRealWork(invocation.Arguments);
}
else
{
  throw new InvalidOperationException();
}

From the point of view of the caller it will be an exception in the called method.

Edit for comment:

Regarding the type of the exception thrown in the generator I have the correct type, not a wrapper:

public interface IDummy
{
    string DoSomething();
}

public class Dummy: IDummy {
    public virtual string DoSomething()
    {
        return string.Empty;
    }
}

public class MyCustomException : Exception {}

public class CustomIntercept: IInterceptor
{
    public void Intercept(IInvocation invocation)
    {
        throw new MyCustomException();
    }
}

internal class Program
{
    private static void Main(string[] args)
    {
        var pg = new ProxyGenerator();
        GetValue(pg.CreateInterfaceProxyWithoutTarget<IDummy>(new CustomIntercept()));
        GetValue(pg.CreateClassProxy<Dummy>(new CustomIntercept()));
        GetValue(pg.CreateClassProxyWithTarget<Dummy>(new Dummy(), new CustomIntercept()));
        GetValue(pg.CreateInterfaceProxyWithTarget<IDummy>(new Dummy(), new CustomIntercept()));
    }

    private static void GetValue(IDummy dummy)
    {
        try
        {
            dummy.DoSomething();
        }
        catch (Exception e)
        {
            Console.WriteLine(e.GetType().Name);
        }
    }
}

All four outputs are MyCustomException

Can you make sure that the TargetInvocationException doesn't come from your own code? What version of the DynamicProxy are you using (I'm using the one in Castle.Core 3.2)

like image 136
samy Avatar answered Nov 15 '22 05:11

samy