I am writing a class which can log the activity of an application during run time. The plan is that the SupportMI string will be sent to a DB, from where I can use some other code to format it properly for readability. I need this class to be usable with .Net-3.5 due to system limitations.What I need is the method name, the values of the parameters passed, and the output of the method (if specified). I also added a timer class to measure performance:using System;using System.Diagnostics;namespace MyTimer{    class MILogger : IDisposable    {        private string SupportMI;        private Stopwatch stopwatch = new Stopwatch();        private string[] parameters;        public static string methodoutput;        public MILogger()        {            stopwatch.Start();        }        public MILogger(params string[] args)        {            stopwatch.Start();            parameters = args;        }        public void Dispose()        {            stopwatch.Stop();            // New stacktrace            StackTrace stackTrace = new StackTrace();            // Method            var method = stackTrace.GetFrame(1).GetMethod();            string methname = method.Name;            SupportMI += methname + (;            // Sorting parameters            for (int i = 0; i < parameters.Length; i++)            {                if (i > 0)                {                    SupportMI += ,;                }                SupportMI += parameters[i];            }            // Timer, methooutput and some punctuation            SupportMI += ) { ;            SupportMI += methodoutput;            SupportMI +=    TIMER:  + stopwatch.ElapsedMilliseconds.ToString();            SupportMI += };        }        public static void SendMI()        {            // Send SupportMI to a database            DBConnection db = new DBConnection(SupportMI);        }    }}Usage:class Program{    static void Main(string[] args)    {        TestMethod(HELLO, HI, 123);        // Other code        MILogger.SendMI();    }    public static string TestMethod(string str, string qwe, int dsad)    {        using (new MILogger(str, qwe, dsad.ToString()))        {            MILogger.methodoutput = str + qwe + dsad.ToString();            return str + qwe + dsad.ToString();                        }    }}And the output looks like this: TestMethod(HELLO,HI,123) { HELLOHI123   TIMER: 1}With this I can more easily debug instances of the application being used by checking that the correct parameters are being passed in each method.I thought it was weird that there is no easier way to get the parameter values. Does anyone have any feedback or thoughts on how this could be done better?I'm also aware that I've used multiple ToStrings()s where this may not be strictly necessary.The DB class:class DBConnection{    public DBConnection(string objecttosend)    {        // connect to DB        using (SqlConnection conn = new SqlConnection())        {            // create the connection string            conn.ConnectionString = ConnectionStringGoesHere;            // open the db connection            conn.Open();            // insert info into DB            SqlCommand insertCmd = new SqlCommand(INSERT INTO IncidentLog (SupportMI) VALUES (@SupportMI), conn);            insertCmd.Parameters.Add(new SqlParameter(@SupportMI, objecttosend));            // execute            insertCmd.ExecuteNonQuery();            // close the db connection            conn.Close();        }    }}Example output of what I'm going for (achieved with a lot of hard-coding):INITIALISE {    Servers.GetServers()    {    }    GetSession()    {        CheckFile()        {            [server file exists] Query(XA7-02)            {                StdOut(QUERY SESSION HelenA /SERVER:XA7-02.mydomain.co.uk)                 {                    ExecuteCommand()                     {                    }                    SESSIONNAME       USERNAME                 ID  STATE   TYPE        DEVICE  ica-cgp#0         User.Name                    2  Active                                      }            }            [correct server]        }    }}INIT    1953    GetProcList(XA7-02){    StdOutAdminList(tasklist /S XA7-02.mydomain.co.uk /FI SESSION eq 2 /FO CSV /NH)    {        ExecuteListCommand()         {        }    }    Creating Proc LYNC.EXE--addingLYNC.EXE--Creating Proc BUSYLIGHT.EXE--addingBUSYLIGHT.EXE--Creating Proc OUTLOOK.EXE--addingOUTLOOK.EXE--Creating Proc SLLAUNCHER.EXE--addingSLLAUNCHER.EXE--Creating Proc TOTALSPEECH.EXE--addingTOTALSPEECH.EXE--Creating Proc PROWC.EXE--addingPROWC.EXE--}Kill(){    ExecAdmin(taskkill /S XA7-02 /PID 6476 /F)     {    }}| EXIT |
Method/parameter tracer
c#;logging;reflection
NamingFields should be named using camelCase casing, so SupportMI -> supportMI. Abbreviations shouldn't be used for naming things, but I assume that MI has a special business meaning to you. If not, consider to rename this as well.  If the field is public one should use PascalCase casing for naming it. For compound words each new word will start with an uppercase letter , so methodoutput -> MethodOutput.  Using abbreviations for names is a no go as well, so andmethname->methodName`.  GeneralBy using the string.Join() method the sorting of the parameter can be improved a lot.  Instead of using string concatenation you should use a StringBuilder and its Append() method. This avoids the creation of a lot of string objects.  The StringBuilder's methods are implemented using a fluent interface which means that the methods return the StringBuilder's instance so one code for instance use it like stringBuilderObject.Append(someValue).Append(someOtherValue)...You could implement this like so  var method = stackTrace.GetFrame(1).GetMethod();var builder = new StringBuilder();builder.Append(method.Name)       .Append(()       .Append(string.Join(,, parameters))       .Append() { )       .Append(MethodOutput)       .Append(   TIMER: )       .Append(stopwatch.ElapsedMilliseconds)       .Append(});  supportMI = builder.ToString();