Tim F
Tim F

Reputation: 143

How to handle List<T> that's stored in an object

I am working on adding some logging to my program to help with tracking function calls and parameters. To do this I have created a function that takes a parameter array of objects and then at runtime I determine the type to define how each object should be handled. The issue I'm running into is if I have a List of SqlParameter in parameters[1], how do I generically handle this so I don't need to define every type of List I can potentially pass in? For each item in the List I am just going to call ToString so I don't have any need to know the actual type. I've tried below to convert it to a list of object but that is failing.

public static string LogParameters(params object[] parameters)
    {
        string returnValue = "\n";

        if (parameters != null)
        {
            for (int i = 0; i < parameters.Length; i++)
            {
                if (parameters[i] == null)
                {
                    returnValue += $"---->null null\n";
                }
                else if (parameters[i].GetType().IsGenericType)
                {
                    // error is happening on this line
                    List<object> objects = (List<object>)parameters[i];

                    returnValue += GetLogParameterTypeText(objects);

                    for (int x = 0; x < objects.Count; x++)
                    {
                        returnValue += GetLogParameterTypeText(objects[x], "----");
                    }
                }
                else if (parameters[i].GetType().IsArray)
                {
                    object[] objects = (object[])parameters[i];

                    returnValue += GetLogParameterTypeText(objects);

                    for (int x = 0; x < objects.Length; x++)
                    {
                        returnValue += GetLogParameterTypeText(objects[x], "----");
                    }
                }
                else
                {
                    returnValue += GetLogParameterTypeText(parameters[i]);
                }
            }
        }

        return returnValue;
    }

Here is a sample of how the function is called

Log.Information($"{LogParameters(fieldName, dataType, fieldValue, panelName)}");

Upvotes: 1

Views: 454

Answers (1)

Luaan
Luaan

Reputation: 63722

Don't use List<T>, use IEnumerable<T>. Unlike a list, enumerables allow for type variance, so List<string> does actually implement IEnumerable<object>, while it does not implement either List<object> or IList<object>.

For bonus points, arrays also implement IEnumerable, so you can change your logic to something like

if (parameters[i] is IEnumerable<object> enumerable)
{
  returnValue += GetLogParameterTypeText(enumerable);

  foreach (var object in enumerable) 
  {
    returnValue += GetLogParameterTypeText(object, "----");
  }
}

You might also want to consider using StringBuilder to build the return value; concatenating strings requires a lot more allocations.

Upvotes: 3

Related Questions