C# и AOP - AOPAlliance (Аспектно-ориентированное программирование), как это работает

У меня просто был очень интересный опыт работы с AOP в C#. У меня есть функция с возвращаемым типом List, который перехватывается, и это все хорошо. Однако функция перехватчика является функцией стиля валидатора и может предотвратить реальную функцию, вызывая и возвращая логическое значение false.

Так что код выглядит примерно так:

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

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

Перехватчик методов выглядит следующим образом

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( ...
 }

Теперь после сбоя проверки значение обновлений на самом деле является логическим значением, а не списком, я думал, что здесь будет какая-то ошибка времени выполнения, но ее не было, поэтому:

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

Но:

updates is bool == false

Поэтому save все равно примет измененный список обновлений и позже будет жаловаться, когда вы попытаетесь его использовать.

Так как же это возможно на безопасном языке типа C#? Кстати, это весна-уп.

Изменить: Также это компилируется, и это работает, я прошел через это несколько раз сейчас.

1 ответ

Решение

Я считаю, что это возможно, потому что Spring.Net генерирует прокси-классы во время выполнения, которые пропускают проверки типов времени компиляции.

Он по существу реализует шаблон декоратора, оборачивающий исходный класс и динамически генерирующий реализацию нового метода. В динамически генерируемом прокси-методе тип возвращаемого значения может быть изменен при записи IL, и.NET позволяет это, потому что не проверяет тип во время выполнения. Конечно, во время компиляции это все еще отлично работает. Это приводит к довольно странному сценарию, описанному выше, в котором ваш статический тип фактически отличается от типа времени выполнения.

Следующее верно, потому что он проверяет фактический тип времени выполнения, который в некоторых случаях может быть разрешен как Boolean.

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

Но следующее не удается, потому что он сравнивает статический тип переменной с логическим, а это не так.

updates is bool == false

Я бы порекомендовал вам не менять тип в Invoke.

Другие вопросы по тегам