Я думаю, что мне нужно то, что люди .net называют «прозрачным динамическим прокси», но все реализации, которые я видел до сих пор (Castle DynamicProxy, Spring.NET AOP и т. д.), требуют, чтобы я сделал хотя бы одно из этого:
- Объявить перехваченный метод виртуальным
- Оберните класс и создайте экземпляры оболочки вместо обернутого класса
- Изменить наследование или реализовать интерфейсы
Очевидно, что если и вызывающий, и вызываемый объекты не являются виртуальными и принадлежат сторонним библиотекам с закрытым исходным кодом, что и происходит, я ничего не могу сделать.
Если бы C# был динамическим языком, таким как Python, я бы сделал что-то вроде этого:
foo = ThirdyPartyLibA.Foo()
def interceptor(self, *args, **kwargs):
do_something_before(self, *args, **kwargs)
result = ThirdyPartyLibB.Bar.intercepted(self, *args, **kwargs)
do_something_after(self, result, *args, **kwargs)
return result
foo.bar.intercepted = interceptor # bar is an instance of ThirdyPartyLibB.Bar
foo.do_its_job() # Foo.do_its_job calls Bar.intercepted
Мне нужно это, чтобы изменить плохое поведение ThirdyPartyLibA.Foo при взаимодействии с ThirdyPartyLibB.Bar. Я точно знаю, что вызывает такое поведение и как именно изменить Foo или Bar, чтобы исправить эту ошибку благодаря дизассемблерам.
Некоторые (очень маловероятные) идеи:
- Разберите ThirdyPartyLibA, внесите изменения в код и сгенерируйте совместимую сборку (вряд ли это сработает, потому что это сборка со строгим именем)
- Отредактируйте двоичный файл, чтобы сделать ошибочные методы Foo виртуальными, и измените все, что необходимо, чтобы он оставался допустимой сборкой, чтобы я мог использовать динамические прокси (очень маловероятно, что это сработает, также по той же причине, что и идея выше)
- Найдите подходящую реализацию прозрачного динамического прокси-сервера (думаю, ее нет на основе этой ветки форума: http://www.pcreview.co.uk/forums/overriding-non-virtual-methods-using-il).-and-reflection-emit-t2605695.html)
- Обратитесь в компанию, создавшую библиотеку (они больше не поддерживают продукт)
- Прекратите использовать библиотеку или используйте альтернативу (невозможно, так как это часть среды выполнения RAD IDE, к которой мы привязаны, потому что существует ОГРОМНОЕ количество кода, написанного с использованием собственного языка IDE)
- Контролируйте вызовы проблемных методов, чтобы избежать ошибки (мы уже сделали это, но это не решило проблему полностью)
У вас есть другая идея?
PS: Извините за мой плохой английский. Кроме того, извините за мой Python. Этот код здесь просто для иллюстрации того, что мне нужно, не воспринимайте его как рецепт, потому что он ужасен.