Parsing C#, finding methods and putting try/catch

2020-03-07 10:29发布

I know it sounds weird but I am required to put a wrapping try catch block to every method to catch all exceptions. We have thousands of methods and I need to do it in an automated way. What do you suggest?

I am planning to parse all cs files and detect methods and insert a try catch block with an application. Can you suggest me any parser that I can easily use? or anything that will help me...

every method has its unique number like 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);
            }
        }

I created this for this; http://thinkoutofthenet.com/index.php/2009/01/12/batch-code-method-manipulation/

标签: c# parsing
18条回答
smile是对你的礼貌
2楼-- · 2020-03-07 11:23

DONT DO IT. There is no good reason for pokemon ("gotta catch em all")error handling.

EDIT: After a few years, a slight revision is in order. I would say instead "at least dont do this manually". Use an AOP tool or weaver like PostSharp or Fody to apply this to the end result code, but make sure to consider other useful tracing or diagnostic data points like capturing time of execution, input parameters, output parameters, etc.

查看更多
smile是对你的礼貌
3楼-- · 2020-03-07 11:26

I guess you could use Aspect Oriented programming, something I would like to my hands dirty with. For example http://www.postsharp.org/aopnet/overview

Although this sort of requirements are indeed evil.

查看更多
叼着烟拽天下
4楼-- · 2020-03-07 11:27

First of all, I'm with StingyJack and Binary Worrier. There's a good reason exceptions aren't caught by default. If you really want to catch exceptions and die slightly nicer, you can put a try-catch block around the Application.Run() call and work from there.

When dealing with outside sources, (files, the Internet, etc), one should (usually) catch certain exceptions (bad connection, missing file, blah blah). In my book, however, an exception anywhere else means either 1) a bug, 2) flawed logic, or 3) poor data validation...

In summary, and to completely not answer your question, are you sure you want to do this?

查看更多
走好不送
5楼-- · 2020-03-07 11:31

See my answer here which describes some of the performance trade offs you will be forced to live with if you use "gotta catch em all" exception handling.

As scott said the best way to do pretty much the same thing is the UnhandledException event. I think jeff actually discussed this very problem in an early SO podcast.

查看更多
我想做一个坏孩纸
6楼-- · 2020-03-07 11:31

I was helping a friend find a memory leak in a C# XNA Game he was writing. I suggested we try and examine how many times each method was getting invoked. In order to keep count, I wrote a python script that added 2 lines to update a Dictionary with the details.

Basically I wrote a python script to modify some 400~ methods with 2 required lines. This code may help someone do more things, like the odd thing the OP wanted.

The code uses the path configured on the 3rd line, and iterates recursively while processing .cs files. It does sub-directories as well.

When it find a cs file, it looks for method declarations, it tries to be as careful as possible. MAKE A BACKUP - I AM NOT RESPONSIBLE IF MY SCRIPT VIOLATES YOUR CODE!!!

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)
查看更多
我命由我不由天
7楼-- · 2020-03-07 11:35

I did some research work that require parsing of C# code about 2 years ago and discover that the SharpDevelop project has source code that does this really well. If you extracted the SharpDevParser project (this was two years ago, not sure if the project name stays the same) from the source code base, you can then use the parser object like this:

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

this gives you the compUnit.Classes which you can iterate through each class and find method within it.

查看更多
登录 后发表回答