【问题标题】:Get names of the params passed to a C# method获取传递给 C# 方法的参数名称
【发布时间】:2011-05-17 03:15:19
【问题描述】:
void MyMethod(string something, params object[] parameters)
    {
      foreach (object parameter in parameters)
      {
        // Get the name of each passed parameter
      }
    }

例如,如果我以以下方式调用该方法,我想获取名称“myFirstParam”和“anotherParam”。

string myFirstParam = "some kind of text";
string anotherParam = 42;
MyMethod("test", myFirstParam, anotherParam);

也许反思就是答案?也许这是不可能的?我知道this question 的存在,但该解决方案在这里不起作用。

(请不要回答“这不是一个好主意”。这不是我的问题。)

【问题讨论】:

  • 我迫不及待想知道您将如何处理这些信息。
  • 好吧,我会给你应得的欢笑。我只是对改进数据库更新包装方法的语法感到好奇,其中 C# 中的参数名称将是 SQL 命令中使用的参数名称。
  • 如果你想使用像 MVC 这样的匿名类型,你可以使用像 MyMethod("test", new { myFirstParam = "some kind of text", anotherParam = 42}); 这样的语法。请参阅weblogs.asp.net/leftslipper/archive/2007/09/24/… 获取一些使其工作的简单代码。
  • 整洁 - 并且 then 我将能够使用反射来获取属性名称。非常好。谢谢。
  • 然后!我会使用动态对象的方法缺少优点,而不必为每个“sql命令”编写新方法,所以你可以只写 dbWrapper.whateverMethod(new { param1 = 'foo', param2 = 'bar'}) 并且能够抓住'whateverMethod'是你想要调用的sproc

标签: c#


【解决方案1】:

这完全不可能。

这里只是一些甚至没有意义的情况:

MyMethod("abc", new object[5]);
MyMethod("abc", "def");
MyMethod("abc", var1 + var2);
MyMethod("abc", SomeMethod());
MyMethod("abc", b ? a : c);
MyMethod("abc", new object()); 
MyMethod("abc", null);

事实上,局部变量名甚至没有被编译到程序集中。

【讨论】:

  • 它在其他情况下是否有效,实际上是传递了一个参数?使用反射?
  • @Richard:不;这不是反射所做的。你需要一个反编译器和一个符号文件。
  • 哦对了,我忘了。您可以获得方法名称等,但实际上并没有像反编译那样获得参数等的符号。感谢您的澄清。 :-)
  • 非常感谢(大家)。我知道这在很多情况下没有意义,但是有一个结论性的答案是不可能的,因为信息不存在,这就是我想要的。谢谢。
【解决方案2】:

除了 SLaks 的答案 - 变量名在运行时根本不可用。变量由堆栈槽表示并由索引寻址。因此,即使对于您提供的示例,您也无法获得此信息,更不用说 SLaks 提供的所有这些示例。反思在这里没有帮助。什么都没有。

【讨论】:

  • 谢谢佳沛,这很有帮助。
【解决方案3】:

这是不可能的,我想知道你为什么需要它。

【讨论】:

  • 这当然有充分的理由......例如,我正在尝试创建一个通用的 SQL Proc 读取/绑定方法,按照惯例,C# vars 将与 proc 具有相同的名称参数,如果我能找到传入参数的名称,我将很容易创建我的SqlParameters,但现在我必须调用 proc 2x,首先获取参数名称,然后实际获取我需要的数据...
【解决方案4】:

我从死里提出这个问题!

查看 C# 6.0 的新 nameof() 运算符。它可以让您完全按照自己的意愿行事,而且实际上并不总是一个坏主意。

一个很好的用例是参数异常或 INotifyPropertyChanged。 (特别是当你在混合中获得继承时)

例子:

interface IFooBar
{
    void Foo(object bar);
}

public class FooBar : IFooBar
{


    public void Foo(object bar)
    {
        if(bar == null)
        {
            //Old and Busted
            //throw new ArgumentException("bar");

            //The new HOTNESS
            throw new ArgumentException(nameof(bar)); // nameof(bar) returns "bar"

        }

        //....
    }

}

现在,如果您在接口 IFooBar 中重命名方法 'Foo' 的参数 'bar',您的参数异常将相应更新(防止您忘记更改“bar”字符串)

其实很整洁!

【讨论】:

  • 这只是以类型安全的方式将变量的名称传递给函数 - 它不允许函数返回并从调用它的函数中获取变量名称。这不可能的原因没有改变。
  • 您可以将参数的名称作为...参数传入
  • 但最初的问题是如何获取调用方法使用的变量的名称。 nameof deos 没有添加任何新功能,它只允许您使用变量 insyead pr 字符串(您可以在示例中使用 throw new ArgumentException("bar"); 做同样的事情
  • 是的,这不是我想要的。但是谢谢,否则,这也是一个非常酷的功能。
  • 如前所述,这不会获得传入变量的名称,只有参数变量本身的名称......与所提出的问题完全无关。问题是这样问的:给定myMethod(paramName1, paramName2) in myMethod(params object[] myParams) 我如何得到paramName1 和paramName2,我们不关心myParams 的名称
【解决方案5】:

这个怎么样;

void MyMethod(string something, object parameters)
{
RouteValueDictionary dic = HtmlHelper.AnonymousObjectToHtmlAttributes(options);
}

MyMethod("test", new { @myFirstParam=""some kind of text", anotherParam=42);

这已经在 System.Web.MVC.Html InputExtension 中实现了。

我受到启发并在我的代码中使用了这种技术。 它非常灵活。

不要为辅助方法中的“Html”命名而烦恼。与 html 无关,也与 helper 方法中的 html 属性无关。

它只是将命名的匿名参数转换为 RouteValueDictionary,这是一个具有IDictionary<string,object> 接口的特殊字典,其中键保存参数名称,对象是参数的值。

【讨论】:

    【解决方案6】:

    使用反射,以及@Martin 的空参数测试示例:

    using System.Reflection;
    
    public SomeMethod(ClassA a, ClassB b, ClassC c)
    {
        CheckNullParams(MethodBase.GetCurrentMethod(), a, b, c);
        // do something here
    }
    

    访问参数名称:

    public void CheckNullParams(MethodBase method, params object[] args)
    {
        for (var i=0; i < args.Count(); i++)
        {
            if (args[i] == null)
            {
                throw new ArgumentNullException(method.GetParameters()[i].Name);
            }
        }
    }
    

    这适用于构造函数和公共方法,但我没有在 VS 中进行单元测试之外的测试,因此可能存在一些运行时 JIT 问题(阅读上面引用的文章)。

    编辑:刚刚注意到,这与linked answer 基本相同。

    【讨论】:

      猜你喜欢
      • 2010-10-19
      • 1970-01-01
      • 2012-12-12
      • 1970-01-01
      • 2019-04-02
      • 2012-11-06
      • 1970-01-01
      • 2013-10-08
      • 2014-07-14
      相关资源
      最近更新 更多