使用自定义属性跳过正文方法

时间:2018-04-13 12:21:46

标签: c# methods custom-attributes microsoft-test-manager

我有以下功能:

public void Test(string testString)
{
     //Do Stuff
}

在我的代码中的某些点,我必须反复检查参数是否为空字符串/ null / whitespace以跳过body方法。我到目前为止通常采用的方法如下:

public void Test(string testString)
{
     if(!string.IsNullOrWhiteSpace(testString))
     {
         //Do Stuff only if string has text in it.
     }
}

或者

public void Test(string testString)
{
     if(string.IsNullOrWhiteSpace(testString)) { return; }
     //Do Stuff only if string has text in it.
}

有没有办法创建一个自定义属性来检查函数的参数是否为空等,以跳过该方法?我有一些经验(基本的东西),有自定义属性,但我无法找到一种方法让属性跳过方法体。

实施的理想最终产品如下:

[SkipIfEmptyParameter]
public void Test(string testString)
{
     //Do Stuff only if string has text in it.
}

当然,如果无法实现属性实现,欢迎提出任何建议,以帮助最小化重复代码。

编辑:我要解决的问题示例。

我有以下方法。我从Microsoft Test Manager获得了我们的测试场景所期望的一些参数(值应该是什么)。有一个SharedStep实现断言用户的信息:

public void AssertUser(UserDTO expectedUserInfo)
{
    VerifyUserName(expectedUserInfo.name);
    VerifyUserSurname(expectedUserInfo.surname);
    VerifyUserAge(expectedUserInfo.age);
    VerifyUserHeight(expectedUserInfo.height);
}

private void VerifyUserName(string name)
{
     //If the string parameter is empty, means the MTM scenario does not
     //want to validate the user's name at this point, so skip the
     //verification below.
     if(string.IsNullOrWhiteSpace(testString)) { return; }

     //Do Stuff only if string has text in it.
}

private void VerifyUserSurname(string surname)
{
     //If the string parameter is empty, means the MTM scenario does not
     //want to validate the user's surname at this point, so skip the
     //verification below.
     if(string.IsNullOrWhiteSpace(testString)) { return; }
     //Do Stuff only if string has text in it.
}

private void VerifyUserAge(string age)
{
     //If the string parameter is empty, means the MTM scenario does not
     //want to validate the user's age at this point, so skip the
     //verification below.
     if(string.IsNullOrWhiteSpace(testString)) { return; }
     //Do Stuff only if string has text in it.
}

private void VerifyUserHeight(string height)
{
     //If the string parameter is empty, means the MTM scenario does not
     //want to validate the user's height at this point, so skip the
     //verification below.
     if(string.IsNullOrWhiteSpace(testString)) { return; }
     //Do Stuff only if string has text in it.
}

" Do Stuff"包含处理WebElements的Selenium实现,可能很耗时,因此如果我们不想验证该特定值,我们就跳过整个方法。

现在,在将事件创建到Microsoft Test Manager时,共享步骤允许测试人员确定将验证页面的哪些元素。如果某些参数为空,那么代码只是跳过块并转到用户想要的w / e验证(仍然,实现是针对用户拥有的每个信息,但我们只是为我们要测试的每个参数赋值,以及没有值的每个参数,只是跳过它的方法体。)

问题是,如果我想改变跳过方法的条件,我将不得不转到每个方法并手动更改IF语句。因此,为什么我会为每个验证信息的方法都有一个属性。

P.S。我在谈论数百种在开始时实施IF的方法。

4 个答案:

答案 0 :(得分:2)

我知道可以使用属性完成此操作的唯一方法是使用post sharp和method interception等产品进行面向方面编程。或者,如果方法是在界面中定义的,也可以使用RealProxy来完成,但似乎有点过分。

答案 1 :(得分:0)

我不认为属性可以实现您想要实现的目标。

但您可以使用自定义方法调用程序:

static void Main(string[] args)
{
    InvokeIfNotNullOrWhitespace((inputStr) => TestMethod(inputStr), null);
    InvokeIfNotNullOrWhitespace((inputStr) => TestMethod(inputStr), "");
    InvokeIfNotNullOrWhitespace((inputStr) => TestMethod(inputStr), "abc");

    // RESULT:
    // Trying to invoke action...
    // Trying to invoke action...
    // Trying to invoke action...
    // I have been invoked!
}

static void InvokeIfNotNullOrWhitespace(Action<string> action, string inputString)
{
    Console.WriteLine("Trying to invoke action...");
    if(!string.IsNullOrWhiteSpace(inputString))
        action.DynamicInvoke(inputString);
}

static void TestMethod(string input)
{
    Console.WriteLine("I have been invoked!");
}

我认为属性不起作用的原因是因为它们无法控制方法内部的内容。相反,“其他外部事物”可以查看这些属性并决定要做什么。

要实现您想要实现的目标,“外部事物”需要查看属性并确定它是否已执行。这与我写的相同:一个统一“检查字符串有效性”程序的外部调用程序。

答案 2 :(得分:0)

这是我的4美分,

  1. 调用属性涉及反思,已经是一个坏主意了 你需要找出属性是否已设置;
  2. 您在代码中避免使用&#34; 1&#34; 易于打字;
  3. 使用方法重载;
  4. 您可以使用Aspect oriented programming,它基本上会在编译时在您的代码中注入以下示例。您可以使用注释控制其工作方式,并且不会对生成的运行时产生负面影响。
  5. 以下是一些变体:

    //1
    if(string.IsNullOrEmpty(testString))
       return;
    //2
    if(string.IsNullOrEmpty(testString) ||string.IsNullOrWhiteSpace(testString) )
       return;
    

    当选择3时,请确保不要混合返回null,或者基于&#34;缺少&#34;的布尔值true / false。文本。只有你知道你的代码应该如何流动。

    也许您正在寻找方法重载 你可以通过在同一个类中创建两个具有相同名称的方法来实现。 你可以从MyMethod(带字符串)调用空的MyMethod(),这样你就不会复制逻辑。

    return string.IsNullOrEmpty(testString)?MyMethod():MyMethod(testString);
    

答案 3 :(得分:0)

你这样做的方式实际上非常好。但正如Evk在评论中指出的那样:你应该提取&#34;跳过检查&#34;进入一个单独的方法,特别是如果检查始终相同并且需要全局更改。使用属性可以解决问题,但使用起来有点复杂。

相反,请查看下面的代码。看起来很清楚,不是吗?不要使用太多评论(并且不要将它们复制粘贴到每个方法中,这是没有用的)。这样,您就可以获得与使用自定义属性相同的好处,但没有使用反射的丑陋。

public void AssertUser(UserDTO expectedUserInfo)
{
    VerifyUserName(expectedUserInfo.name);
    VerifyUserSurname(expectedUserInfo.surname);
    VerifyUserAge(expectedUserInfo.age);
    VerifyUserHeight(expectedUserInfo.height);
}

private void VerifyUserName(string name)
{
    if (ShouldSkipValidation(name)) return;
    // code here...
}

private void VerifyUserSurname(string surname)
{
    if (ShouldSkipValidation(surname)) return;
    // code here...
}

private void VerifyUserAge(string age)
{
    if (ShouldSkipValidation(age)) return;
    // code here...
}

private void VerifyUserHeight(string height)
{
    if (ShouldSkipValidation(height)) return;
    // code here...
}

// The MTM scenario does not want to validate values that satisfy the check below
private bool ShouldSkipValidation(string value)
{
    return string.IsNullOrWhiteSpace(value) || value == "<>";
}