在运行时解析参数名称

xyz*_*xyz 20 c# reflection anonymous-types

可能重复:
查找传递给C#中函数的变量名称

在C#中,有没有办法(更好的方法)在运行时解析参数的名称?

例如,在以下方法中,如果重命名方法参数,则还必须记住更新传递给ArgumentNullException的字符串文字.

    public void Woof(object resource)
    {
        if (resource == null)
        {
            throw new ArgumentNullException("resource");
        }

        // ..
    }
Run Code Online (Sandbox Code Playgroud)

Jus*_*ier 26

单程:

static void Main(string[] args)
{
  Console.WriteLine("Name is '{0}'", GetName(new {args}));
  Console.ReadLine();
}
Run Code Online (Sandbox Code Playgroud)

此代码还需要一个支持功能:

static string GetName<T>(T item) where T : class
{
  var properties = typeof(T).GetProperties();
  Enforce.That(properties.Length == 1);
  return properties[0].Name;
}
Run Code Online (Sandbox Code Playgroud)

基本上,代码的工作原理是定义一个新的匿名类型,其中包含一个属性,该属性包含您想要的参数名称.GetName()然后使用反射来提取该属性的名称.

这里有更多细节:http://abdullin.com/journal/2008/12/13/how-to-find-out-variable-or-parameter-name-in-c.html

  • Eewww - 同时,整洁!我真的不能决定这是否是一种可怕的匿名类型滥用. (5认同)
  • @Robert Seder右键单击 - Refactor不会更改字符串文字; 这是问题的动机. (2认同)

Jon*_*eet 15

简答:不,没有.(那简洁吗?;)

(编辑:贾斯汀的回答可能很重要.它在我的嘴里留下了不好的味道,但它实现了"不需要将参数名称放入字符串"的目标.我不认为我真的算AOP,因为这真的改变为一种完全不同的方法,而不是回答从方法中获取参数名称的原始问题.)

更长的答案:有一种方法可以找出方法的所有参数,但我不认为它在这种情况下有用.

这是一个显示来自几个方法的参数名称的示例:

using System;
using System.Reflection;

class Test
{
    static void Main()
    {
        Foo(null);
        Bar(null);
    }

    static void Foo(object resource)
    {
        PrintParameters(MethodBase.GetCurrentMethod());
    }

    static void Bar(object other)
    {
        PrintParameters(MethodBase.GetCurrentMethod());
    }

    static void PrintParameters(MethodBase method)
    {
        Console.WriteLine("{0}:", method.Name);
        foreach (ParameterInfo parameter in method.GetParameters())
        {
            Console.WriteLine(" {0} {1}",
                              parameter.ParameterType,
                              parameter.Name);
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

这就是这样,但是如果你有多个参数而你想抛出一个合适的异常,你怎么知道(以安全的方式)使用哪个?理想情况下,您需要以下内容:

public void Woof(object resource)
{
    if (resource == null)
    {
        throw new ArgumentNullException(infoof(resource));
    }

    // ..
}
Run Code Online (Sandbox Code Playgroud)

神话infoof操作员将返回的地方ParameterInfo.不幸的是,这不存在.

  • Downvoters:请发表评论. (6认同)

Bro*_*ski 5

我处理了同样的问题.获取参数名称有两种方法,但性能最佳的方法是深入了解IL.你可以在我的博客文章中看到我在这个问题上的实现示例.从参数验证中解脱出来.

这种方法的一个警告是你需要将参数名称作为委托传递,但为更清洁的代码付出的代价很小:

public void SomeMethod(string value)
{
    Validate.Argument(() => value).IsNotNull().IsNotEmpty();
}
Run Code Online (Sandbox Code Playgroud)

这比以下更清洁,更清晰:

public void SomeMethod(string value)
{
    if (value == null)
    {
        throw new ArgumentNullException("value");
    }
    if (value == string.Empty)
    {
        throw new ArgumentException("Value cannot be an empty string.", "value");
    }
}
Run Code Online (Sandbox Code Playgroud)

静态方法方法允许我在一个流畅的界面中将许多方法链接在一起.最初返回一个Argument对象,它只允许一个基本的null测试,它返回一个ReferenceArgument对象,然后可以进行额外的验证.如果被测对象是值类型,则可以使用不同的测试.

API允许进行许多常见测试,但很难捕获所有可能的测试,因此为了提供灵活性,通用测试方法允许提供表达式或函数,而在前者的情况下,表达式实际上可以用作错误消息.

我的示例仅涵盖了一些基础知识,但您可以轻松扩展接口以检查范围并抛出ArgumentOutOfRangeExceptions或从特定基类继承的测试对象或实现接口.有一些类似的实现,但我还没有看到任何获取参数名称.

  • 问题在于开箱即用的方法过于臃肿,它会通过分散你的方式来消除方法试图做的事情.此外,还存在一个维护问题,即首先放入引发异常的参数名称,然后在参数名称更改时保持其名称.我所做的就是将这个逻辑转变为一个易于使用的流畅界面,其中包含较少(但仍然存在)的混乱.如果不需要这种方法那么就没有那么多博客文章推送他们的Guard API或.net 4.0的Microsoft代码合同. (3认同)