Сделать хук на метод
От: GhostCoders Россия  
Дата: 11.09.14 08:40
Оценка:
Здраствуйте!

Есть готовая программа на С# с системой плагинов.
В этой программе есть интерфейс ISomeThing и какой-то класс, который реализует этот интерфейс.

В своем плагине я могу создать собственную реализацию данного интерфейса.

Кроме того, в этой программе уже есть стандартная реализация этого интерфейса (при помощи какого-то внутреннего класса).
Я могу получить ссылку на экземпляр этого класса, и вызвать у нее,
например, stdImpl.GetType().Name — показывает название этого класса (из какого-то внутреннего закрытого пространства имен someProgram.Impl).

Мне нужно перехватить значение переменной, которое возвращает этот класс, когда основная программа вызывает его методы.
Если я вызываю эти методы напрямую, то всегда получаю null.
Потому как в эти методы передаются некоторые аргументы, мне не до конца понятные. Я испробовал разные варианты.

У меня другой вопрос. Можно ли средствами .NET (это называется type introspection, как я понял?) как-нибудь заменить такой класс на класс-заглушку (или proxy),
который будет только перенапрявлять вызовы в стандартную реализацию, и запоминать результаты?

Спасибо!
Третий Рим должен пасть!
Re: Сделать хук на метод
От: Rinbe Россия  
Дата: 11.09.14 09:31
Оценка:
Здравствуйте, GhostCoders, Вы писали:

GC>У меня другой вопрос. Можно ли средствами .NET (это называется type introspection, как я понял?) как-нибудь заменить такой класс на класс-заглушку (или proxy),

GC>который будет только перенапрявлять вызовы в стандартную реализацию, и запоминать результаты?

А что напрямую не сделать? Сделайте реализацию ISomeThing, которая будет содержать ссылку на известную реализацию и перенаправлять все вызовы ей, а заодно и выводить нужную инфу для анализа. Если ISomeThing подгружается динамически, то аналогично: делаем плагин — обертка над существующийм плагином.
Отредактировано 11.09.2014 16:29 AndrewVK . Предыдущая версия .
Re[2]: Сделать хук на метод
От: GhostCoders Россия  
Дата: 11.09.14 10:29
Оценка:
Здравствуйте, Rinbe, Вы писали:

R>А что напрямую не сделать? Сделайте реализацию ISomeThing, которая будет содержать ссылку на известную реализацию и перенаправлять все вызовы ей, а заодно и выводить нужную инфу для анализа. Если ISomeThing подгружается динамически, то аналогично: делаем плагин — обертка над существующийм плагином.


Если бы так можно было бы сделать, то я бы сюда не писал
В той программе, есть такой термин, "служба" называется (не путать со службами Windows).

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

services.AddService(typeof(MyData), typeof(ISomeThing), new myImplementation());

но я делаю так (условный код)
ISomeThing previousService = services.GetSerive(typeof(StandardData), typeof(ISomeThing)); // получаю стандартную реализацию для некоего стандартного класса данных StandardData
// previousService.GetType().Name возвращает имя его реализующего класса
MyService my_service = new MyServiceImplementation(); // MyServiceImplementation реализует ISomeThing
my_service.previousService_ = previousService; // передаем моему сервису ссылку на предудущую службу для перенапрявления вызовов
services.AddService(typeof(StandardData), typeof(ISomeThing), my_service);


но, увы, методы моей реализации не вызываются (сделал лог и по точкам останова смотрел)

а если регистрировать мою службу не для стандартного класса данных StandardData, а на свой, то мои методы вызываются:
ISomeThing previousService = services.GetSerive(typeof(StandardData), typeof(ISomeThing)); // получаю стандартную реализацию для некоего стандартного класса данных StandardData
// previousService.GetType().Name возвращает имя его реализующего класса
MyService my_service = new MyServiceImplementation(); // MyServiceImplementation реализует ISomeThing
my_service.previousService_ = previousService; // передаем моему сервису ссылку на предудущую службу для перенапрявления вызовов
services.AddService(typeof(MyData), typeof(ISomeThing), my_service); // MyData - это какой-то мой класс


но мне нужно перехватить данные для класса StandardData, плюс предыдущая реализация в таком случае возвращает null

Result MyService::Method1(Object arg1)
{
   Result tmp_res = previousService_.Method1(arg1); // вызывает предудущую реализацию
   // а тут всегда null, так как prevuiousService_.Method1() ожидает аргумент типа StandardData, а тут ему передается MyData
   
   // если делать вот так например,
   Result tmp_res = previousService_.Method1(GlobalProject.GetStandardData());
   // то на вход ему передается нужный тип данных, но, по-видимому он находится не в том состоянии
   // то есть и в этом случае возвращается null
}


Идеи? Можно ли как-то в рантайме заменить реализацию метода Method1() для стандартного класса, или его эземпляр?
Третий Рим должен пасть!
Re[3]: Сделать хук на метод
От: Rinbe Россия  
Дата: 11.09.14 10:36
Оценка:
Здравствуйте, GhostCoders, Вы писали:

GC>Здравствуйте, Rinbe, Вы писали:


R>>А что напрямую не сделать? Сделайте реализацию ISomeThing, которая будет содержать ссылку на известную реализацию и перенаправлять все вызовы ей, а заодно и выводить нужную инфу для анализа. Если ISomeThing подгружается динамически, то аналогично: делаем плагин — обертка над существующийм плагином.


GC>Если бы так можно было бы сделать, то я бы сюда не писал

GC>В той программе, есть такой термин, "служба" называется (не путать со службами Windows).

GC>Идеи? Можно ли как-то в рантайме заменить реализацию метода Method1() для стандартного класса, или его эземпляр?


Знаю Microsoft Fakes, но это только в тестовых проектах работает, может еще что то есть.
Отредактировано 11.09.2014 10:38 Rinbe . Предыдущая версия .
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.