C # и AOP - AOPAlliance (Аспектно-ориентированное программирование), как это работает - PullRequest
6 голосов
/ 26 августа 2011

У меня только что был очень интересный опыт работы с 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 Ответ

6 голосов
/ 27 августа 2011

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

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

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

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

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

updates is bool == false

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

...