Похоже, что если для метода существует только один параметр массива типов, значение параметра, переданного моему методу LogException()
, больше не является массивом.Первый элемент массива передается вместо целого массива
Если в методе есть несколько параметров или если один параметр не является массивом, он работает как ожидалось. Но когда я пытаюсь передать массив, кажется, что первое значение массива становится переданным параметром.
Все комментарии включены, чтобы объяснить и показать проблему. Сначала проблема возникает в «точке 4»; как только неправильное значение найдено, информация о параметрах, хранящаяся в моем исключении, неверна. В других пунктах выясняется последующая путаница, которая возникает. Я понятия не имею, как это решить.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace Testapp
{
class Program
{
static void Main(string[] args)
{
string[] tmp1 = new string[2];
tmp1[0] = "val1";
tmp1[1] = "val2";
//please look at point 1
TestMethod1(tmp1);
//please look at point 2
TestMethod2(tmp1, "just a value");
}
private static void TestMethod1(string[] ArrayType)
{
try
{
throw new System.Exception("blow");
}
catch (System.Exception ex)
{
LogException(ex, ArrayType);
foreach (System.Collections.DictionaryEntry entry in ex.Data)
{
string tmp1 = entry.Key.ToString();
string tmp2 = entry.Value.ToString();
//point 1 (for param:ArrayType... well there is only 1 parameter)
//the value of tmp2 = val1
//and should be {val1,val2}
System.Diagnostics.Debugger.Break();
}
}
}
private static void TestMethod2(string[] ArrayType, string StringType)
{
try
{
throw new System.Exception("blow");
}
catch (System.Exception ex)
{
LogException(ex, ArrayType, StringType);
foreach (System.Collections.DictionaryEntry entry in ex.Data)
{
string tmp1 = entry.Key.ToString();
string tmp2 = entry.Value.ToString();
//point 2 (for param:ArrayType)
//the value of tmp2 = {val1,val2} (correct, this what i expected)
//please look at point 3
System.Diagnostics.Debugger.Break();
}
}
}
[System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.NoInlining)]
public static void LogException(System.Exception Exception, params object[] args)
{
using (CallerInfo callerinfo = new CallerInfo(1))
{
callerinfo.AddParameterInfo(Exception, args);
}
}
private class CallerInfo : IDisposable
{
private System.Reflection.ParameterInfo[] parameterinfos = null;
private string identifiername = string.Empty;
private string assemblyname = string.Empty;
public void AddParameterInfo(System.Exception Exception, params object[] sourceargs)
{
if (parameterinfos == null) return;
string locationname = identifiername + " - param:";
foreach (System.Reflection.ParameterInfo ParameterInfo in parameterinfos)
{
string KeyName = locationname + ParameterInfo.Name;
object parameter = null;
try
{
System.Diagnostics.Debugger.Break();
//point 4
//the next line goes wrong when there is ONLY 1 parameter on a method of type array
parameter = sourceargs[ParameterInfo.Position];
}
catch
{
parameter = null;
}
if (parameter == null)
{
if (!Exception.Data.Contains(KeyName))
{
Exception.Data.Add(KeyName, "*NULL*");
}
}
else
{
if (ParameterInfo.ParameterType.IsArray)
{
//point 3
//this is where i got confused
//the check if (ParameterInfo.ParameterType.IsArray) is returning true.. correct the first parameter in both methods are of type array
//however for TestMethod1 (that is having ONLY 1 parameter) the value of parameter (see point 4) is NOT an array anymore?????
//for TestMethod2 (that is having 2 parameters, but the SAME first parameter as passed in TestMethod1) the value of parameter (see point 4) is an array what is correct
System.Diagnostics.Debugger.Break();
if (parameter.GetType().IsArray)
{
string arrayvaluelist = "{";
try
{
System.Collections.ArrayList arraylist = new System.Collections.ArrayList((System.Collections.ICollection)parameter);
foreach (object arrayitem in arraylist)
{
if (arrayitem == null) { arrayvaluelist = arrayvaluelist + "*NULL*,"; continue; }
arrayvaluelist = arrayvaluelist + arrayitem.ToString() + ",";
}
arrayvaluelist = arrayvaluelist.Substring(0, arrayvaluelist.Length - 1);
arrayvaluelist = arrayvaluelist + "}";
}
catch
{
arrayvaluelist = "Error in constructing the arrayvalue list for parameter: " + ParameterInfo.Name;
}
if (!Exception.Data.Contains(KeyName))
{
Exception.Data.Add(KeyName, arrayvaluelist);
}
}
else
{
//point 5 -- i shouldn't be here !!!!
System.Diagnostics.Debugger.Break();
if (!Exception.Data.Contains(KeyName))
{
Exception.Data.Add(KeyName, parameter.ToString() + " warning wrong value is returned.");
}
}
}
else
{
if (!Exception.Data.Contains(KeyName))
{
Exception.Data.Add(KeyName, parameter.ToString());
}
}
}
}
}
[System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.NoInlining)]
public CallerInfo(int Level)
{
try
{
System.Diagnostics.StackTrace stackTrace = new System.Diagnostics.StackTrace();
System.Reflection.MethodBase methodbase = stackTrace.GetFrame(Level + 1).GetMethod();
parameterinfos = methodbase.GetParameters();
assemblyname = methodbase.ReflectedType.Assembly.ManifestModule.Name;
identifiername = methodbase.ReflectedType.FullName + "." + methodbase.Name;
}
catch
{
//broken
}
}
void IDisposable.Dispose()
{
parameterinfos = null;
}
}
}
}