Oto szybki i brudny sposób robienia tego, co chcesz. Jest oparty na jednym z powyższych komentarzy, który wskazuje na SebbyLive. To tylko dowód koncepcji, nie próbowałbym jej używać w produkcji.
Podstawową ideą jest zmiana kompilatora projektu, który chcesz zmodyfikować. I ten zmieniony kompilator zrobi wstrzyknięcie kodu. Musisz więc napisać nowy kompilator (AopCompiler.exe) i ustawić go jako narzędzie do budowania w swoim projekcie.
Ustawianie AopCompiler.exe jako narzędzie budowania jest łatwe, w projekcji plik, trzeba by dodać następujące dwa wiersze:
<CscToolPath>$(SolutionDir)AopCompiler\bin\Debug</CscToolPath>
<CscToolExe>AopCompiler.exe</CscToolExe>
AopCompiler powinna być prosta aplikacja konsoli. To robi także modyfikację kodu i kompilację. Jeśli nie chcesz zmodyfikować kod źródłowy, tylko budować, to najprostszym sposobem jest wywołanie csc.exe siebie:
static void Main(string[] args)
{
var p = Process.Start(@"C:\Program Files (x86)\MSBuild\14.0\Bin\csc.exe",
string.Join(" ", args));
p.WaitForExit();
}
Więc jeśli to ustawić tak daleko, że masz normalny proces budowy, bez aspektu tkania.
W tym momencie, jeśli sprawdzisz, co jest w args
, zobaczysz, że istnieje ścieżka pliku do pliku .RSP, który zawiera wszystkie parametry wiersza polecenia dla csc.exe. Oczywiście te parametry zawierają również wszystkie nazwy plików .CS. Więc możesz sparsować ten plik .RSP i znaleźć wszystkie pliki .CS, które są częścią kompilacji.
Przy pomocy plików C#, przepisanie można wykonać z Roslyn. Istnieje wiele samouczków na temat CSharpSyntaxRewriter
, na przykład here i here. Musisz napisać niestandardową CSharpSyntaxRewriter
, która sprawdza dany atrybut, a następnie dodać rejestrowanie do początku znalezionych metod. Dodawanie rejestrowania na końcu każdej metody jest nieco trudniejsze, ponieważ może istnieć wiele punktów wyjścia. Aby je znaleźć, możesz użyć analizy przepływu sterowania. Wbudowana analiza przepływu kontrolnego Roslyn może dać dokładnie to, czego szukasz, właściwość ExitPoints
zawiera zestaw instrukcji wewnątrz regionu, który przeskakuje do lokalizacji poza regionem.
Aby uzyskać model semantyczny (a następnie wykonać analizę CFG) można zrobić coś takiego:
public override SyntaxNode VisitMethodDeclaration(MethodDeclarationSyntax node)
{
var semanticModel = _compilation.GetSemanticModel(node.SyntaxTree);
// semanticModel.AnalyzeControlFlow(node.Block)
return node;
}
Wreszcie, aby przetworzyć każdy z plików wejściowych, twój AopCompiler, wystarczy po prostu zadzwonić metoda przeszukiwacza Visit
w katalogu głównym drzewa. To wytworzy zmodyfikowane drzewo, które możesz zapisać do pliku. (Możesz zmodyfikować oryginalny plik lub zapisać wynik na nowym i odpowiednio zmienić plik .RSP.)
Przepraszamy za brak kompleksowego rozwiązania, ale mam nadzieję, że wystarczy, aby zacząć.
Jest też [Fody] (https://github.com/Fody/Fody) –
Czy to nie jest to, co chcesz osiągnąć: http://www.sebbylive.com/articles/programming/aspect_oriented_programming_roslyn.aspx? Jego podstawowym pomysłem jest wykonanie modyfikacji i kompilacji za pomocą samodzielnego pliku wykonywalnego i dodanie tego exe jako narzędzia do kompilacji. – Tamas
Lubię takie pytania, gdy z jednej strony masz legendę mówiącą [Nie] (https://social.msdn.microsoft.com/forums/vstudio/en-US/3593b4d9-c3f0-4e94-818a-7958930aeb4e/injecting -code-into-an-existing-assembly) i [quotes] (https://gist.github.com/SimonCropp/8485964) twierdząc, że zespół Roslyn powiedział, że będzie obsługiwał wtryskiwanie kodu, prawdopodobnie nie dla pierwszego release'. @ Bjørn-Roger Kringsjå, czy możesz wskazać, jak można oczekiwać, że Roslyn wdroży to ** w inny sposób ** do normalnych implementacji: http://www.codeproject.com/Articles/14334/AOP-using-System- Refleksja -Emit-Code-Injection-IL –