6

I just had a very interesting experience with AOP in C#. I have a function with a return type List which is being intercepted and that's all well and good. However the interceptor function is a validator style function and can prevent the real function by being called and returning the boolean false.

So the code looks a little bit like this:

List<Update> updates = Manager.ValidateAndCreate();

// protected void Save(List<Update> updates) { ....
Save(updates);

The Method Interceptor looks like the following

public class ExceptionAdvice : AopAlliance.Intercept.IMethodInterceptor {

    public object Invoke(AopAlliance.Intercept.IMethodInvocation invocation) {

        if (isValid(invocation)) {
            return invocation.Proceed();
        } else {
            return false;
        }
    }

    private bool isValid( ...
 }

Now after validation fails the value of updates is actually a boolean not a List, I thought there would be some kind of runtime error here but there was not, so:

updates.GetType().Name == "Boolean"

But:

updates is bool == false

So save will still accept its mutated list of updates and will complain later on when you try to use it.

So how is this possible in a type safe language like C#? btw it's spring-aop.

Edit: Also this does compile and it does work i've stepped through it a few times now.

6
  • Also I'll point out that this is C# 3.5 so there is no Dynamic or anything Commented Aug 26, 2011 at 6:40
  • 1
    I don't believe this is possible, is your program still compiling once u explicitly type the return? Is your debug file out of date? Commented Aug 26, 2011 at 6:57
  • @TheCodeKing I've updated the question again, hope it helps Commented Aug 27, 2011 at 0:23
  • 1
    AOP is a general programming concept. C# doesn't fully support AOP out of the box. AOPAlliance seems to be a third-party framework (part of Spring.NET?) designed to support AOP. Can you change the title/tags to reflect this? Commented Aug 27, 2011 at 1:51
  • @Lavinski: What is the exact signature (return type) of Manager.ValidateAndCreate();? Are you proxying an interface or are you using an inheritance based proxy? Commented Aug 28, 2011 at 16:14

1 Answer 1

6

I believe this is possible because Spring.Net is emitting proxy classes at runtime which skip compile time type checks.

It essentially implements a decorator pattern wrapping the original class and dynamically generating a new method implementation. In the dynamically generated proxy method the return type can be changed when it writes the IL, and .NET allows it because it doesn't check the type at runtime. At compile time of course it's also still perfectly valid. This leads to the rather weird scenario above whereby your static type is actually different to the runtime type.

The following is true because it's checking the actual runtime type, which can in cases resolve to Boolean.

updates.GetType().Name == "Boolean"

But the following fails because it's comparing the static type of the variable to Boolean, which it's not.

updates is bool == false

I would recommend that you don't change the type within Invoke.

Sign up to request clarification or add additional context in comments.

6 Comments

+1: It's probably a better idea to raise an event or throw an exception anyway.
@TheCodeKing - Spring.net doesn't create proxies with a different method signature. A proxy implements the interface(s) implemented by the target instance, or (in the case of an inheritance based proxy) implements all public virtual members of the target instance.
@TheCodeKing: I just ran a quick test; as expected Spring.Aop throws an InvalidCastException when I try to return another type. OP's scenario can only happen if Manager.ValidateAndCreate(); has return type object.
But then obviously OP's code example "that looks a little bit like this" wouldn't compile, so I'm a bit at a loss here.
I've reworded slightly to clarify the method signature remains the same, it's just the proxy implementation that returns a different type. I've reproduced this in VS, in debugger the type shows as System.Collections.Generic.List<string> {bool}.
|

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.