如何在C#中将任何表达式作为字符串?

时间:2011-08-23 09:07:28

标签: .net keyword string-literals

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

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));
    }
}

3 个答案:

答案 0 :(得分:2)

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

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

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

答案 1 :(得分: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块中的代码之外,抛出异常后,方法中的代码不会执行。请参阅this article

答案 2 :(得分: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);
}

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