Может ли производный класс в CLR перехватывать / маскировать методы родительского класса, сохраняя при этом intellisense? - PullRequest
0 голосов
/ 25 мая 2011

Возможно ли для CLR создать объект X, который наследуется от объекта Y, где

  • Объект Y имеет тип Object
  • Все методы Y доступны для объекта X.
  • Призыватели Объекта X думают, что они видят все объекты Y
  • Объект X маскирует методы выше и выполняет некоторую «работу» перед запуском каждого метода
  • Эта «работа» может включать подсчет количества вызовов или некоторый произвольный код
  • Объект X должен иметь возможность работать с любым объектом (это нормально, если он не работает с Запечатанными объектами)

Альтернативная реализация может использовать Generics, где Object T<Y> предоставляет все методы, события и свойства содержимого объекта Y

Ответы [ 2 ]

1 голос
/ 25 мая 2011

Да.Это называется проксированием объекта. Castle DynamicProxy предназначен именно для этого. Krzysztof Koźmic подготовил превосходный учебник об этом .

Он работает путем создания объекта (X в вашем сценарии) во время выполнения, который наследуется от объекта, который вы хотите прокси (объект Y).Вы предоставили объект, который реализует IInterceptor, который вызывается при вызове определенных методов - вы указываете их в классе параметров генерации прокси.

Единственное предостережение в том, что методы, которые вы хотите перехватить, должны быть виртуальными, новы, вероятно, можете обойти это, обернув объект в прокси в другой, который предоставляет виртуальные методы (хотя я думаю, что вы, вероятно, захотите прокси-объект, потому что это реальная боль).

0 голосов
/ 25 мая 2011

Альтернативой прокси-серверам времени выполнения, которые, по-видимому, соответствуют вашим требованиям (запуск произвольного кода при вызове методов на Y), но не ваш вопрос (стратегия создания подклассов), будет AOP с использованием решений времени компиляции, таких как PostSharp или Запоздалая мысль . Этот подход позволяет вам вводить код в существующие методы в скомпилированной сборке и делать практически все, что вы хотите.

PostSharp работает, позволяя определять атрибуты (аспекты), которые описывают, как вы хотите изменить ваши классы. Вы должны поместить эти атрибуты в методы, типизированные, сборки и т. Д., И когда PostSharp запускается как шаг после сборки, он будет искать эти атрибуты и выполнять преобразования в скомпилированной сборке.

Запоздалая мысль работает аналогично, используя схему атрибутов для определения поправок, применяемых к типам в вашей сборке. Однако Afterthought позволяет вам указать эти атрибуты / поправки в одной сборке и применить их к другой сборке, так что вы можете фактически изменить целевую сборку, которая не имеет никаких атрибутов или ссылок на Afterthought или потенциально на библиотеки, которые вы вводите в нее. , Я добавил эту функцию в Afterthought, основываясь на отзывах сообщества, желая иметь возможность выполнять элегантные преобразования без установления зависимости от инструмента AOP (в этом случае Afterthought) и, возможно, в тех случаях, когда исходный код для сборки больше не доступен.

Это пример использования Afterthought для автоматического вывода времени выполнения каждого вызова метода с измененным типом:

public override void Amend(Method method)
{
    method.Context<Stopwatch>()

        .Before((T instance, string method, object[] parameters)
            => { var s = new Stopwatch(); s.Start(); return s; })

        .After((T instance, string method, Stopwatch stopwatch, object[] parameters)
            => Console.WriteLine(method + ": " + stopwatch.ElapsedMilliseconds);
}

В этом случае каждый метод с измененным типом собирается создать экземпляр System.Diagnostics.Stopwatch в начале каждого метода и записать имя метода и время выполнения в конце каждого метода.

...