1

在许多情况下,我们需要表达式、参数、语句等的名称。例如:

public abstract void Log(string methodName, string parameterName, string message);

public void FooMethod(string value)
{
    if (value == null)
    {
        this.Log("FooMethod", "value", "The value must be whatever...");
        throw new ArgumentNullException("value");
    }

    if (value.Length < 5)
    {
        this.Log("FooMethod", "value.Length", "The value length must be whatever...");
        throw new ArgumentException("value");
    }
}

有什么方法可以自动获取这些字符串文字,例如使用可以像这样使用的关键字typeof(string)?还是有一种基于反射的简单而高效的方法?

我不是在寻找一种方法来检查和记录这个参数(这实际上只是一个例子)。我正在寻找一种方法来获取部分代码为string.

以下会更准确,可以由编译器检查,也可以在重构代码时考虑:

public void FooMethod(string value)
{
    if (value == null)
    {
        this.Log(literal(this.FooMethod), literal(value), "The parameter '" + literal(value) + "' must be whatever...");
        throw new ArgumentNullException(literal(value));            
    }

    if (value.Length < 5)
    {
        this.Log(literal(this.FooMethod), literal(value.Length), "The value length must be whatever...");
        throw new ArgumentException(literal(value));
    }
}
4

3 回答 3

2

您可以为所有可能的类型创建这样的静态方法。下面是方法名称。

public static string GetString(Action obj)
{
    return obj.Method.Name;
}

public static string GetString(Delegate obj )
{
    return obj.Method.Name;
}
于 2011-08-23T09:31:24.050 回答
1

听起来您需要StackTrace.GetFrame。此方法将为您提供所需的 StackFrame 对象,您可以从中找到此信息。

查看以下代码示例

StackFrame fr = new StackFrame(1,true);
StackTrace st = new StackTrace(fr);
this.Log.WriteEntry(fr.GetMethod().Name,
                    fr.GetMethod().GetParameters()[0].Name,
                    "The value must be whatever...");

顺便说一句,在您的第二个代码示例中,Log 方法调用将永远不会执行,因为在调用之前会引发异常。抛出异常后,方法中的任何代码都不会执行,除了finally块中的代码。见这篇文章

于 2011-08-23T09:14:19.607 回答
0

这取决于你的目标是什么。如果您希望获得运行时值 Martin Doms回答可能是解决方案。如果您希望能够将 ArgumentNullException 链接到特定的参数名称,并确保在更改名称时可以使用重构,您可以执行以下操作:

 public static void NotNull<T>(Expression<Func<IEnumerable<T>>> exp)
        {
            var expBody = exp.Body as MemberExpression;
                T value = exp.Compile().Invoke();
                if (value == null){
                    string memberName;
                    if (expBody != null){
                        memberName = expBody.Member.Name;
                    } else{
                        memberName = "member";
                    }
                    throw new ArgumentNullException(memberName, memberName + " cannot be null");
                }
        }

然后你可以像这样使用它:

public void Method(string value){
  Ensure.NotNull(()=>value);
}

它将检查值是否为空,如果值为空,则将适当的消息格式化给 ArgumentNullException。但是,如果您使用的是 .NET 4.0,我建议您使用合同来代替这些东西。并不是说它实际上在这里解决了您的特殊需求,但是与“老式方式”相比,使用 Contracts 进行参数检查在文档和静态分析方面有很多好处

于 2011-08-23T09:48:32.223 回答