Разбор C #, поиск методов и установка try / catch для всех методов - PullRequest
1 голос
/ 06 января 2009

Я знаю, это звучит странно, но я должен поставить блокировку try catch для каждого метода, чтобы перехватить все исключения. У нас есть тысячи методов, и мне нужно сделать это автоматически. Что вы предлагаете?

Я планирую проанализировать все файлы cs, определить методы и вставить блок try catch с приложением. Можете ли вы предложить мне любой парсер, который я могу легко использовать? или что-нибудь, что поможет мне ...

каждый метод имеет свой уникальный номер, например, 5006

public static LogEntry Authenticate(....)
        {
            LogEntry logEntry = null;
            try
            {
                ....
                return logEntry;
            }

            catch (CompanyException)
            {
                throw;
            }

            catch (Exception ex)
            {
                logEntry = new LogEntry(
                    "5006",
                    RC.GetString("5006"), EventLogEntryType.Error,
                    LogEntryCategory.Foo);

                throw new CompanyException(logEntry, ex);
            }
        }

Я создал это для этого; http://thinkoutofthenet.com/index.php/2009/01/12/batch-code-method-manipulation/

Ответы [ 18 ]

0 голосов
/ 17 октября 2011

Я помогал другу найти утечку памяти в C # XNA Game, которую он писал. Я предложил попытаться выяснить, сколько раз вызывался каждый метод. Чтобы вести счет, я написал скрипт на python, который добавил 2 строки для обновления словаря с подробной информацией.

По сути, я написал скрипт на python для модификации 400 методов с двумя необходимыми строками. Этот код может помочь кому-то сделать больше вещей, например, странную вещь, которую хотел ОП.

Код использует путь, заданный в 3-й строке, и рекурсивно повторяется при обработке файлов .cs. Это также делает подкаталоги.

Когда он находит файл cs, он ищет объявления методов, он старается быть максимально осторожным. СДЕЛАЙТЕ РЕЗЕРВНОЕ КОПИРОВАНИЕ - Я НЕ ОТВЕТСТВЕН, ЕСЛИ МОЙ СКРИПТ НАРУШАЕТ ВАШ КОДЕКС !!!

import os, re

path="D:/Downloads/Dropbox/My Dropbox/EitamTool/NetworkSharedObjectModel"
files = []

def processDir(path, files):
    dirList=os.listdir(path)
    for fname in dirList:
        newPath = os.path.normpath(path + os.sep + fname)
        if os.path.isdir(newPath):
            processDir(newPath, files)
        else:
            if not newPath in files:
                files.append(newPath)
                newFile = handleFile(newPath)
            if newPath.endswith(".cs"):
                writeFile(newPath, newFile)

def writeFile(path, newFile):
    f = open(path, 'w')
    f.writelines(newFile)
    f.close()

def handleFile(path):
    out = []
    if path.endswith(".cs"):
        f = open(path, 'r')
        data = f.readlines()
        f.close()

        inMethod = False
        methodName = ""
        namespace = "NotFound"
        lookingForMethodDeclerationEnd = False
        for line in data:
            out.append(line)
            if lookingForMethodDeclerationEnd:
                strippedLine = line.strip()
                if strippedLine.find(")"):
                    lookingForMethodDeclerationEnd = False
            if line.find("namespace") > -1:
                namespace = line.split(" ")[1][0:-2]
            if not inMethod:
                strippedLine = line.strip()
                if isMethod(strippedLine):
                    inMethod = True
                    if strippedLine.find(")") == -1:
                        lookingForMethodDeclerationEnd = True
                    previousLine = line
            else:
                strippedLine = line.strip()
                if strippedLine == "{":
                    methodName = getMethodName(previousLine)
                    out.append('            if (!MethodAccess.MethodAccess.Counter.ContainsKey("' + namespace + '.' + methodName + '")) {MethodAccess.MethodAccess.Counter.Add("' + namespace + '.' + methodName + '", 0);}')
                    out.append("\n" + getCodeToInsert(namespace + "." + methodName))
                    inMethod = False
    return out

def getMethodName(line):
    line = line.strip()
    lines = line.split(" ")
    for littleLine in lines:
        index = littleLine.find("(")
        if index > -1:
            return littleLine[0:index]


def getCodeToInsert(methodName):
    retVal = "          MethodAccess.MethodAccess.Counter[\"" + methodName + "\"]++;\n"
    return retVal

def isMethod(line):
    if line.find("=") > -1 or line.find(";") > -1 or line.find(" class ") > -1:
        return False
    if not (line.find("(") > -1):
        return False
    if line.find("{ }") > -1:
        return False
    goOn = False
    if line.startswith("private "):
        line = line[8:]
        goOn = True
    if line.startswith("public "):
        line = line[7:]
        goOn = True
    if goOn:
        return True
    return False

processDir(path, files)
0 голосов
/ 12 апреля 2010

Я провел некоторую исследовательскую работу, которая требует синтаксического анализа кода C # около 2 лет назад, и обнаружил, что проект SharpDevelop имеет исходный код, который делает это действительно хорошо. Если вы извлекли проект SharpDevParser (это было два года назад, но не уверен, что имя проекта останется прежним) из базы исходного кода, вы можете использовать объект синтаксического анализатора следующим образом:

CSharpBinding.Parser.TParser = new CSharpBinding.Parser.TParser();
SIP.ICompilationUnitBase unitBase = sharpParser.Parse(fileName);

это дает вам классы compUnit.Class, которые вы можете перебирать в каждом классе и находить в нем метод.

0 голосов
/ 12 апреля 2010

Если вам действительно нужно это сделать, альтернативой обертыванию исключения будет каждый раз использовать Exception.Data для захвата дополнительной информации, а затем перебрасывать исходное исключение ...

catch (Exception ex)
{
  logEntry = new LogEntry("5006",
                    RC.GetString("5006"), EventLogEntryType.Error,
                    LogEntryCategory.Foo);
  ex.Data.Add("5006",logEntry);
  throw;
}

Теперь на верхнем уровне вы можете просто сбросить содержимое ex.Data, чтобы получить всю дополнительную информацию, которая вам может понадобиться. Это позволяет вам помещать имена файлов, аргументы пользователя и ... всю другую полезную информацию в коллекцию .Data, чтобы понять, почему произошло исключение.

0 голосов
/ 06 января 2009

Если вам абсолютно необходимо добавить блок try / catch для каждого метода и ответа Скотта (AppDomain.UnhandledException) недостаточно, вы также можете посмотреть на перехватчики. Я считаю, что проект Castle имеет довольно хорошую реализацию методов-перехватчиков.

0 голосов
/ 06 января 2009

То есть вы не хотите вставлять один и тот же блок try-catch в каждую функцию, верно? Вам нужно будет адаптировать каждую попытку к каждой функции. Вот Это Да! Похоже, долгий путь к «упрощению» отладки.

Если пользователь сообщает об ошибке в производственной среде, почему вы не можете просто запустить Visual Studio, воспроизвести шаги и выполнить отладку?

0 голосов
/ 06 января 2009

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

0 голосов
/ 06 января 2009

Полагаю, вы могли бы использовать Аспектно-ориентированное программирование, что-то, чем я бы хотел испачкать руки. Например http://www.postsharp.org/aopnet/overview

Хотя такого рода требования действительно злые.

0 голосов
/ 06 января 2009

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

Посмотрите на Сесил (см. веб-сайт ). Это библиотека, которая позволяет вам напрямую изменять байт-код, используя этот подход, вся ваша проблема может быть решена с помощью пары сотен строк кода C # .

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...