从调用方法中的变量中获取名称 - 创建调用方法签名、参数和值
Get name from variable in calling method - creating calling method signature, parameters and values
我正在寻找一种方法来获取传递给扩展方法的变量的名称。我想在调用变量中包含参数的名称。听起来很奇怪,让我解释一下。
假设这段测试代码
private static void TestingMethod(string firstParam, int secondParam, bool thirdParam)
{
try
{
throw new InvalidOperationException("This named optional params stuff, it's just not working boss");
}
catch (Exception ex)
{
GenericLog_Exception(ex, "it's on fire, please help");
}
}
在最后一行,您可以看到正在记录的异常。我希望能够提供可选参数支持。所以开发者可以在需要的时候添加参数信息。
我在 Whosebug 上看过很多关于这个的帖子,有很多不同的方法。主要的是;它不能完全通用地完成。
部分代码解释:
static string GetCallingMethodSignature()
{
StackTrace stackTrace = new StackTrace();
// Get calling method name
var callingMethod = stackTrace.GetFrame(1).GetMethod();
var callingMethod_Name = callingMethod.Name;
// get calling method params
string retVal = string.Empty;
var callingMethod_Parameters = callingMethod.GetParameters();
retVal = callingMethod_Name + "(";
foreach (var param in callingMethod_Parameters)
{
retVal += param.Name + ": " + param.ToString() + ",";
}
retVal.Remove(retVal.Length - 1, 1);
retVal += ")";
return retVal;
}
现在,此测试代码正在获取调用方法名称及其参数。即,参数的名称。但不是他们的价值观。 param.tostring() 部分仅 returns 类型名称。不是价值。我一直在读这个,似乎这不能通过反射来完成。
于是我又换了一种方式,为什么不提供开发者认为适合日志记录的参数呢。反正你大部分时间都不需要它们。
private static string GenericLog_Exception(Exception exceptionData, string extraInformation, params KeyValuePair<string, object>[] parameters)
因此,这是一种新的测试方法,我将选择的参数提供给异常记录方法。但如果你想让这项工作成功,每次打电话都是一项艰巨的工作。
private static void TestingMethod(string firstParam, int secondParam, bool thirdParam)
{
try
{
throw new InvalidOperationException("This named optional params stuff, it's just not working boss");
}
catch (Exception ex)
{
GenericLog_Exception(ex, "it's on fire, please help", new KeyValuePair<string, object>[]{
new KeyValuePair<string, object>("firstParam", firstParam),
new KeyValuePair<string, object>("secondParam", secondParam),
new KeyValuePair<string, object>("thirdParam", thirdParam)
});
}
}
现在可以了。但正如所说,我发现底部很麻烦。我在考虑扩展方法,所以我可以缩短每个 kvp 的创建时间。
internal static class ExtensionMethodsForTesting
{
internal static KeyValuePair<string, object> AsKeyValuePair(this string parameter)
{
var name = nameof(parameter);
return new KeyValuePair<string, object>(name, parameter);
}
}
这将用作
GenericLog_Exception(ex, "it's on fire, please help", new KeyValuePair<string, object>[] { firstParam.AsKeyValuePair() });
这让我遇到了我以前遇到的同样问题; nameof(参数),当然,returns "parameter"。我还必须为每种类型制作几个扩展方法。或者检查扩展方法中的类型以确保我得到正确的值。
所以,简而言之:我怎样才能得到这个调用扩展方法的变量的名称?
您可以执行以下操作 "hack"。将您的方法签名更改为以下内容:
private static string GenericLog_Exception(
Exception exceptionData,
string extraInformation,
params Expression<Func<object>>[] parameters)
现在您的呼叫站点看起来更干净了:
GenericLog_Exception(ex,
"it's on fire, please help",
() => firstParam,
() => secondParam,
() => thirdParam);
并且您可以通过以下方式从表达式中提取参数信息(为方便起见,使用 C# 元组支持):
private static (object Value, string ParamName) GetParameterInfo
(Expression<Func<object>> expr)
{
//First try to get a member expression directly.
//If it fails we know there is a type conversion: parameter is not an object
//(or we have an invalid lambda that will make us crash)
//Get the "to object" conversion unary expression operand and then
//get the member expression of that and we're set.
var m = (expr.Body as MemberExpression) ??
(expr.Body as UnaryExpression).Operand as MemberExpression;
return (expr.Compile().Invoke(), m.Member.Name);
}
我正在寻找一种方法来获取传递给扩展方法的变量的名称。我想在调用变量中包含参数的名称。听起来很奇怪,让我解释一下。
假设这段测试代码
private static void TestingMethod(string firstParam, int secondParam, bool thirdParam)
{
try
{
throw new InvalidOperationException("This named optional params stuff, it's just not working boss");
}
catch (Exception ex)
{
GenericLog_Exception(ex, "it's on fire, please help");
}
}
在最后一行,您可以看到正在记录的异常。我希望能够提供可选参数支持。所以开发者可以在需要的时候添加参数信息。
我在 Whosebug 上看过很多关于这个的帖子,有很多不同的方法。主要的是;它不能完全通用地完成。
部分代码解释:
static string GetCallingMethodSignature()
{
StackTrace stackTrace = new StackTrace();
// Get calling method name
var callingMethod = stackTrace.GetFrame(1).GetMethod();
var callingMethod_Name = callingMethod.Name;
// get calling method params
string retVal = string.Empty;
var callingMethod_Parameters = callingMethod.GetParameters();
retVal = callingMethod_Name + "(";
foreach (var param in callingMethod_Parameters)
{
retVal += param.Name + ": " + param.ToString() + ",";
}
retVal.Remove(retVal.Length - 1, 1);
retVal += ")";
return retVal;
}
现在,此测试代码正在获取调用方法名称及其参数。即,参数的名称。但不是他们的价值观。 param.tostring() 部分仅 returns 类型名称。不是价值。我一直在读这个,似乎这不能通过反射来完成。
于是我又换了一种方式,为什么不提供开发者认为适合日志记录的参数呢。反正你大部分时间都不需要它们。
private static string GenericLog_Exception(Exception exceptionData, string extraInformation, params KeyValuePair<string, object>[] parameters)
因此,这是一种新的测试方法,我将选择的参数提供给异常记录方法。但如果你想让这项工作成功,每次打电话都是一项艰巨的工作。
private static void TestingMethod(string firstParam, int secondParam, bool thirdParam)
{
try
{
throw new InvalidOperationException("This named optional params stuff, it's just not working boss");
}
catch (Exception ex)
{
GenericLog_Exception(ex, "it's on fire, please help", new KeyValuePair<string, object>[]{
new KeyValuePair<string, object>("firstParam", firstParam),
new KeyValuePair<string, object>("secondParam", secondParam),
new KeyValuePair<string, object>("thirdParam", thirdParam)
});
}
}
现在可以了。但正如所说,我发现底部很麻烦。我在考虑扩展方法,所以我可以缩短每个 kvp 的创建时间。
internal static class ExtensionMethodsForTesting
{
internal static KeyValuePair<string, object> AsKeyValuePair(this string parameter)
{
var name = nameof(parameter);
return new KeyValuePair<string, object>(name, parameter);
}
}
这将用作
GenericLog_Exception(ex, "it's on fire, please help", new KeyValuePair<string, object>[] { firstParam.AsKeyValuePair() });
这让我遇到了我以前遇到的同样问题; nameof(参数),当然,returns "parameter"。我还必须为每种类型制作几个扩展方法。或者检查扩展方法中的类型以确保我得到正确的值。
所以,简而言之:我怎样才能得到这个调用扩展方法的变量的名称?
您可以执行以下操作 "hack"。将您的方法签名更改为以下内容:
private static string GenericLog_Exception(
Exception exceptionData,
string extraInformation,
params Expression<Func<object>>[] parameters)
现在您的呼叫站点看起来更干净了:
GenericLog_Exception(ex,
"it's on fire, please help",
() => firstParam,
() => secondParam,
() => thirdParam);
并且您可以通过以下方式从表达式中提取参数信息(为方便起见,使用 C# 元组支持):
private static (object Value, string ParamName) GetParameterInfo
(Expression<Func<object>> expr)
{
//First try to get a member expression directly.
//If it fails we know there is a type conversion: parameter is not an object
//(or we have an invalid lambda that will make us crash)
//Get the "to object" conversion unary expression operand and then
//get the member expression of that and we're set.
var m = (expr.Body as MemberExpression) ??
(expr.Body as UnaryExpression).Operand as MemberExpression;
return (expr.Compile().Invoke(), m.Member.Name);
}