2

so I'm trying to add some stuff to my debug output and I'm currently trying to dynamically get the class variables and the values of it. I tried some stuff and got it working quite fast when I added the cod ein the same class like this:

var bindingFlags = BindingFlags.Instance |
        BindingFlags.Static |
        BindingFlags.NonPublic |
        BindingFlags.Public;

Console.WriteLine("");
foreach (var variable in typeof(TestingStuff).GetFields(bindingFlags))
{
    Debugger.Debug(Context.Player.GetUsername(), $"{variable.Name}: variable.GetValue(this)}");
}
Console.WriteLine("");

This outputs the following result:

15:47:09 [Test1] _currentTarget:
15:47:09 [Test1] _currentlyPathing: False
15:47:09 [Test1] _moveToTest:
15:47:09 [Test1] _botName: Test_ZerGo01

This is exactly what I want, but when I try to pass that stuff to my actual "Debugger" output I can't use this because it's a static method. I have no idea what I should replace the this with.

This is my "debugger" method:

public static void Error(string playerName, Exception ex, Type classType = null)
{
    ...
    if (classType != null)
    {
        var bindingFlags = BindingFlags.Instance |
            BindingFlags.Static |
            BindingFlags.NonPublic |
            BindingFlags.Public;

        if (classType.GetFields(bindingFlags).Length > 1)
        {
            message += DebuggerLine("Plugin Class Variables") + nL;

            foreach (var variable in classType.GetFields(bindingFlags))
            {
                message += DebuggerLine(variable.Name, variable.GetValue(???).ToString()) + nL;
            }
        }

        message += DebuggerLine() + nL;
    }
    ...
}

Could someone please tell me what I do?

Faven
  • 23
  • 1
  • 3

2 Answers2

1

You will need to pass the target object instance to your Error method and then use that instance in place of this. Note that you can get the class type from the object instance, so you don't have to pass that in. Here is what the modified method would look like.

public static void Error(string playerName, Exception ex, object instance = null)
{
    ...
    if (instance != null)
    {
        var bindingFlags = BindingFlags.Instance |
            BindingFlags.Static |
            BindingFlags.NonPublic |
            BindingFlags.Public;

        Type classType = instance.GetType();
        if (classType.GetFields(bindingFlags).Length > 1)
        {
            message += DebuggerLine("Plugin Class Variables") + nL;

            foreach (var variable in classType.GetFields(bindingFlags))
            {
                message += DebuggerLine(variable.Name, variable.GetValue(instance).ToString()) + nL;
            }
        }

        message += DebuggerLine() + nL;
    }
    ...
}

Then, call the method like this:

try
{
    ...
}
catch (Exception ex)
{
    Debugger.Error(Context.Player.GetUsername(), ex, this);
}
Brian Rogers
  • 125,747
  • 31
  • 299
  • 300
  • Well what object are you passing to it? In the code in the top part of your question, where you said it was working exactly as you want-- what class is that in? You need to pass that instance (`this`) to `Error` – Brian Rogers Oct 27 '19 at 15:55
  • Well, I'm not exactly sure if I'm passing the class the right way, but this is what I was doing: `Debugger.Error(Context.Player.GetUsername(), e, typeof(TestingStuff));` I want to get all variables and values from `TestingStuff`. – Faven Oct 27 '19 at 16:04
  • You have a `TestingStuff` instance that has the variables, right? So you should do: `Debugger.Error(Context.Player.GetUsername(), e, testingStuffInstance);` If you are calling `Error` from inside the `TestingStuff` instance, then it would be: `Debugger.Error(Context.Player.GetUsername(), e, this);` – Brian Rogers Oct 27 '19 at 16:58
  • I passed the wrong object, that's why it didn't work, thanks. – Faven Oct 27 '19 at 17:07
0

You can use null for static members instead of object instance reference.

if ( variable.IsStatic ) 
  message += DebuggerLine(variable.Name, variable.GetValue(null).ToString()) + nL;
else
if ( instance != null )
  message += DebuggerLine(variable.Name, variable.GetValue(instance).ToString()) + nL;
else
  // Manage method call mistmatch: 
  // add an error string to the message or do nothing or what you want

Modify the method signature as:

public static void Error(string playerName,
                         Exception ex,
                         Type classType = null,
                         object instance = null)

https://learn.microsoft.com/dotnet/api/system.reflection.fieldinfo.getvalue