如何获取在c#中作为参数传递的表达式的字符串表示形式?

时间:2018-05-14 19:48:05

标签: c#

我有一个静态方法,用于检查参数......

require(myStringVariable);

如果该值不符合某些要求,我只想显示一条消息。

是否可以显示作为参数传递的变量(或表达式)的名称? (在C ++中,带有stringize运算符的宏可以完成这项工作。在C#中是否有相同的工具或其他工具?)

更新:我没有搜索nameof(myStringVariable)之类的内容。实际上,我想把这个方法称为:

require(bareFname + ".ext");

如果表达式没有通过检查,那么我会在之类的方法中做

static void required(... theExpressionArgument)
{
    string value = evaluate theExpressionArgument;
    if (value.Length == 0)
    {
        Console.WriteLine("ERROR: Non empty value is required for the expression "
                          + theExpressionArgument);
    }
}

1 个答案:

答案 0 :(得分:2)

基于this answer,您可以像这样重写您的方法:

public static void RequireNotEmpty(Expression<Func<string>> lambda)
{
    // Get the passed strings value:
    string value = lambda.Compile().Invoke();

    // Run the check(s) on the value here:
    if (value.Length == 0)
    {
        // Get the name of the passed string:
        string parameterName = ((MemberExpression) lambda.Body).Member.Name;

        Console.WriteLine($"ERROR: Non empty value is required for the expression '{parameterName}'.");
    }
}
然后可以像这样调用

string emptyString = "";
RequireNotEmpty(() => emptyString);

并写

  

错误:表达式&#39; emptyString&#39;需要非空值。

请注意,上面的代码假定您只想检查字符串。如果情况并非如此,您可以使用签名public static void RequireNotEmpty<T>(Expression<Func<T>> lambda),该签名将适用于任何类型T

此外,我将方法重命名为更具可读性和更有意义的方法。

编辑:建议

阅读完评论后,我认为可能是你想要的:

public static class Checker
{
    private static T GetValue<T>(Expression<Func<T>> lambda)
    {
        return lambda.Compile().Invoke();
    }

    private static string GetParameterName<T>(Expression<Func<T>> lambda)
    {
        return ((MemberExpression) lambda.Body).Member.Name;
    }

    private static void OnViolation(string message)
    {
        // Throw an exception, write to a log or the console etc...
        Console.WriteLine(message);
    }

    // Here come the "check"'s and "require"'s as specified in the guideline documents, e.g.

    public static void RequireNotEmpty(Expression<Func<string>> lambda)
    {
        if(GetValue(lambda).Length == 0)
        {
            OnViolation($"Non empty value is required for '{GetParameterName(lambda)}'.");
        }
    }

    public static void RequireNotNull<T>(Expression<Func<T>> lambda) where T : class
    {
        if(GetValue(lambda) == null)
        {
            OnViolation($"Non null value is required for '{GetParameterName(lambda)}'.");
        }
    }

    ...
}

现在你可以像这样使用Checker类:

public string DoStuff(Foo fooObj, string bar)
{
    Checker.RequireNotNull(() => fooObj);
    Checker.RequireNotEmpty(() => bar);

    // Now that you checked the preconditions, continue with the actual logic.
    ...
}

现在,当您使用无效参数调用DoStuff时,例如

DoStuff(new Foo(), "");

消息

  

&#39; bar&#39;

需要非空值

写入控制台。