2013-06-18 14 views
8

Nie jestem nawet pewien, czy jest to możliwe, więc przepraszam, jeśli nie. Przeszukałem dość obszernie i nie znalazłem tego, czego szukam.Przesłanianie metody w DLL przy użyciu refleksji

Zasadniczo mamy aplikację wyprodukowaną przez osobę trzecią, która, aby być całkowicie bezceremonialnym, jest śmieciem. Mamy konkretny problem i udało się namierzyć problem za pomocą ILSpy do metody w bibliotece DLL. Oczywiście nie mamy (ani nie możemy uzyskać) kodu źródłowego, a dana firma nie chce naprawić problemu w rozsądnych ramach czasowych.

Tak więc, zbadaliśmy różne drogi dochodzenia i nie wymyślimy niczego. Dążyłem do sprawdzenia, czy można tego dokonać za pomocą refleksji i jest to ostatnia nadzieja na to, aby to zadziałało. W skrócie, co chciałbym zrobić to:

  • Tworzenie prostych bibliotekę klas o takiej samej nazwie jak istniejący DLL
  • użycie odbicie importować metod z istniejącej biblioteki DLL
  • Jakoś nadpisuję tę metodę własnym, poprawnym kodem
  • Odbuduj kod, więc mam nową bibliotekę DLL, zawierającą 99% funkcjonalności istniejącej biblioteki DLL, ale z moim kodem nadpisywania zapewniającym poprawną funkcjonalność.

Znalazłem podczas moich badań TypeBuilder.DefineMethodOverride oraz stronę ze StackOverflow, która wydaje się podobna, ale nie do końca tego, czego szukam.

http://msdn.microsoft.com/en-us/library/system.reflection.emit.typebuilder.definemethodoverride.aspx

Is there a way to "override" a method with reflection?

Wszelkie porady mile widziane!

Andrew

Edit

innych możliwych I ma pomysł był aby wytworzyć częściową klasę zawierającą funkcję sterowania ręcznego, ale to nie wydaje się wykonalne albo.

+0

Zastanawiasz się, czy działa tu podejście oparte na przechwytywaniu - coś takiego jak Castle DynamicProxy: http://www.castleproject.org/projects/dynamicproxy/ - oczywiście nie zastąpiłbyś całkowicie metody wywołania metody, ale z pewnością możesz przechwycić/uchwyt błędu i poprawianie (o tak, i to zależy od tego, czy klasa ma metody wirtualne). – Charleh

+0

Dlaczego po prostu nie stworzysz klasy, jak powiedziałeś, która wywołuje klasę strony trzeciej dla większości rzeczy z wyjątkiem metody, którą chcesz zastąpić? Lub wyprowadzić z tej klasy i użyć innej nazwy dla tej metody? Też naprawdę potrzebujesz, aby być wewnątrz 1 unikalnej biblioteki DLL? Dlaczego nie podzielić go na 2? – ppetrov

Odpowiedz

6

Możesz zastąpić metodę tylko wtedy, gdy jest wirtualna i nie ma znaczenia, czy robisz to poprzez odbicie czy statycznie. Sugerowałbym użycie dekompilatora (dostępnych jest wiele darmowych) i naprawienie kodu w MSIL. Następnie możesz wygenerować nowy zestaw z MSIL.

+0

Tak, właśnie sprawdziłem, a metoda nie jest wirtualna, więc jeden pomysł przez okno. Właśnie sprawdzam teraz dekompilatory - dziękuję za twoją radę. – Andrew

+0

co ze znakiem i publickeytoken? czy pozostaje taki sam? –

+0

Jeśli biblioteka DLL jest podpisana (ma silną nazwę), to po modyfikacji należy zrezygnować z certyfikatu silnej nazwy. –

0

Myślę, że twój pierwszy pomysł jest dobry. Jeśli klasa osoby trzeciej nie jest sealed, możesz ją wyprowadzić i dodać własną metodę o innej nazwie, aby poprawić niewłaściwe zachowanie. Jeśli potrzebujesz go w 1 dll, możesz użyć IlMerge.

Jeśli twoja trzecia klasa jest zaplombowana, możesz po prostu mieć instancję tej klasy strony trzeciej w swojej nowej klasie i wywołać metody w razie potrzeby.

Ale musisz sprawdzić, czy metoda chcesz „nadpisać” nie nazywa się wewnątrz tej biblioteki, ponieważ jeśli jest to rozwiązanie nie będzie działać ...

To nie jest bardzo czysty, ale może to być tymczasowe rozwiązanie w czasie, gdy firma, która edytuje bibliotekę, naprawia problem.

A kiedy zostanie naprawiony, musisz zmienić nazwę używanej metody, więc nie będzie to zbyt czasochłonne.

0

Z tego, co opisałeś, polecam modyfikację oryginalnego zestawu. Proces jest zasadniczo

  • Dekompilacji zespołu do MSIL, C# lub inny język tak zdecydujesz
  • Modyfikacja dekompilowana montaż obejmować zmiany
  • rekompilacji montaż stosując zmodyfikowaną źródło

Z tego, co widzę, można zrobić tylko to, ale może wymagać zakupu Resharpera (sam tego nie próbowałem).

Alternatywnie można użyć ILDasm dekompilować cały zespół do jednego pliku, należy zmodyfikować plik, a następnie skompilować go za pomocą ILAsm

0

wiem, że idę w trochę późno na to, ale zgodziłbym się z Charleh; jeśli masz klasę, która nie zachowuje się dobrze i nie sprzyja substytucji, ale przynajmniej deklaruje jej metody jako virtual, masz szczęście. Następujących zastosowań odniesień do Castle.Core i Patterns:

var interceptor = new DelegateInterceptor(proceed: call => 
{ 
    if(ShouldCallProceed(call)) call.Proceed(); 
    else AlternativeLogic(); 
}); 

var generator = new ProxyGenerator(); 
var proxy = generator.CreateClassProxy<UncooperativeType>(interceptor); 

proxy.RubbishMethod(); 

Wziąłem też swobodę świadczenia a running sample of this w LINQPad. Pokazuje różnicę między metodami, które umożliwiają przechwytywanie (virtual) a tymi, które tego nie robią. Pokazuje również użyteczny sposób wychwytywania wyjątków bez całego kodu z użyciem Try.Do z Patterns.

Powiązane problemy