Как перехватить вызов метода в C #?

RepositoryBase является не базовым классом MyEntityRepository. Вы ищете общую дисперсию , которая существует в C # в ограниченной степени, но здесь не применима.

Предположим, что у вашего класса RepositoryBase был такой метод:

void Add(T entity) { ... }

Теперь рассмотрим:

MyEntityRepository myEntityRepo = GetMyEntityRepo(); // whatever
RepositoryBase baseRepo = (RepositoryBase)myEntityRepo; 
baseRepo.Add(new OtherEntity(...));

Теперь вы добавили другой тип сущности в MyEntityRepository ... и это не может быть прав.

В принципе, общая дисперсия является безопасной только в определенных ситуациях. В частности, общая ковариация (именно это вы описываете здесь) безопасна только тогда, когда вы только когда-либо получаете значения «API»; общая контравариантность (которая работает наоборот) безопасна только тогда, когда вы когда-либо вводили значения в API (например, общее сравнение, которое может сравнивать любые две формы по площади, можно рассматривать как сравнение квадратов).

В C # 4 это доступно для общих интерфейсов и общих делегатов, а не для классов - и только для ссылочных типов. См. MSDN для получения дополнительной информации, прочитайте & lt; plug & gt; прочитайте C # в глубине, 2-е издание , глава 13 & lt; / plug & gt; или блога Эрика Липперта по этой теме. Кроме того, я рассказал об этом в NDC в июле 2010 года - видео доступно здесь .

145
задан Journeyman 25 August 2008 в 09:14
поделиться

8 ответов

C# не является ориентированным языком AOP. Это имеет некоторые функции AOP, и можно эмулировать некоторых других, но AOP создания с C# является болезненным.

я искал способы сделать точно, что Вы хотели сделать, и я не нашел простого способа сделать это.

Насколько я понимаю, это - то, что Вы хотите сделать:

[Log()]
public void Method1(String name, Int32 value);

и чтобы сделать это, у Вас есть две основных опции

  1. , Наследовали Ваш класс от MarshalByRefObject или ContextBoundObject и определяют атрибут, который наследовался IMessageSink. Эта статья имеет хороший пример. Необходимо рассмотреть nontheless, как который с помощью MarshalByRefObject понизится производительность черт, и я имею в виду его, я говорю о 10x производительность, потерянная, так думайте тщательно прежде, чем попробовать это.

  2. другая опция состоит в том, чтобы ввести код непосредственно. Во времени выполнения имея в виду необходимо будет использовать отражение, чтобы "считать" каждый класс, получить его атрибуты и ввести вызов appropiate (и в этом отношении я думаю, что Вы не могли использовать Отражение. Испустите метод, поскольку я думаю Отражение. Испустите не позволил бы Вам вводить новый код в уже существующем методе). Во время проектирования это будет означать создавать расширение компилятора CLR, который у меня нет честно идеи о том, как это сделано.

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

67
ответ дан Jorge Córdoba 25 August 2008 в 09:14
поделиться
  1. Запись Ваша собственная библиотека AOP.
  2. отражение Использования для генерации регистрирующегося прокси по экземплярам (не уверенный, если можно сделать это, не изменяя некоторую часть существующего кода).
  3. Перезапись блок и вводят Ваш код входа (в основном то же как 1).
  4. Хост CLR и добавляет вход на этом уровне (я думаю, что это - самое трудное решение реализовать, не уверенный, если у Вас есть необходимые рычаги в CLR хотя).
-1
ответ дан kokos 25 August 2008 в 09:14
поделиться

Я не знаю решения, но мой подход был бы следующие.

Украшают класс (или его методы) с пользовательским атрибутом. Где-то в другом месте в программе, позвольте инициализации функциональное отражение все типы, прочитайте методы, украшенные атрибутами, и введите некоторый код IL в метод. Это могло бы на самом деле быть более практично к замена метод тупиком, который звонит LogStart, фактический метод и затем LogEnd. Кроме того, я не знаю, можно ли изменить методы с помощью отражения, таким образом, это могло бы быть более практично для замены целого типа.

1
ответ дан Konrad Rudolph 25 August 2008 в 09:14
поделиться
  • 1
    < C-R> + работает для вставки в экс-командную строку. Но Как я копирую экс-команду в буфер обмена? – Ayman 7 September 2009 в 11:28

Смотрите на это - Довольно тяжелый материал.. http://msdn.microsoft.com/en-us/magazine/cc164165.aspx

Существенный .net - поле Дона имело главу по тому, что Вам нужен названный Перехват. Я очистил часть его здесь (Извините за цвета шрифта - у меня была темная тема тогда...) http://madcoderspeak.blogspot.com/2005/09/essential-interception-using-contexts.html

4
ответ дан Gishu 25 August 2008 в 09:14
поделиться
  • 1
    Что относительно того, чтобы копировать текст you' ve ввел в командную строку, но haven' t выполнил его все же и don' t хотят. Как Вы копируете его тогда? – trusktr 7 April 2013 в 07:21

Если Вы пишете, что класс - называет его Трассировкой - который реализует интерфейс IDisposable, Вы могли обернуть все тела метода в

Using( Tracing tracing = new Tracing() ){ ... method body ...}

В классе Трассировки, который Вы могли дескриптор логика трассировок в методе конструктора/Располагать, соответственно, в классе Трассировки для отслеживания ввод и выход методов. Таким образом, что:

    public class Traced 
    {
        public void Method1(String name, Int32 value) {
            using(Tracing tracer = new Tracing()) 
            {
                [... method body ...]
            }
        }

        public void Method2(Object object) { 
            using(Tracing tracer = new Tracing())
            {
                [... method body ...]
            }
        }
    }
10
ответ дан Steen 25 August 2008 в 09:14
поделиться
  • 1
    Проблема состоит в том, что я не могу выбрать команду для копирования его. Я использую мышь для выбора, и затем это работает, но it' s не действительно энергия путь. – Ayman 7 September 2009 в 11:29

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

Другая опция состоит в том, чтобы использовать профильный API для введения кода в методе, но это - действительно хардкор.

45
ответ дан plog17 25 August 2008 в 09:14
поделиться
  • 1
    I' m не уверенный я следую. Нормальное перемещение управляет работой с рывком. Если Вы хотите что-то более необычное, можно использовать визуальный режим (v/V) – Brian Rasmussen 7 September 2009 в 11:56

Вы могли потенциально использовать Шаблон "декоратор" GOF и 'украсить' все классы та трассировка потребности.

Это, вероятно, только действительно практично с контейнером МОК (но как указатель ранее можно хотеть рассмотреть перехват метода, если Вы собираетесь спуститься по пути МОК).

1
ответ дан Stacy A 25 August 2008 в 09:14
поделиться
  • 1
    То же для энергии (и emacs, я воображаю): Вы переходите вокруг кодовой базы с помощью ctags или cscope. Это - просто гладкий GUI. I' m собирающийся ожидать (очень, очень терпеливо) для энергии, чтобы начать управлять окнами с несколькими панелями в стиле xmonad или потрясающий. – Wang 19 March 2010 в 18:39

вам нужно проверить Айенде, чтобы узнать, как он это сделал: http://ayende.com/Blog/archive/2009/11/19/can-you-hack-this-out.aspx

1
ответ дан 23 November 2019 в 22:32
поделиться
Другие вопросы по тегам:

Похожие вопросы: