c# - 在 C# 中临时存储和重新设置属性值

标签 c#

当我在特定代码库中编写测试时,我经常需要在新添加的代码之前设置一个静态属性,并在离开时将其重新设置回来。示例

public void SomeMethod(){
    val oldVal = Notifier.DoNotify;
    Notifier.DoNotify = false;

    // Some code...

    Notifier.DoNotify = oldVal;
}

我认为这种方式很丑陋,我想要更好的东西,这也使得忘记重新设置值变得更困难。

我尝试煮点东西,结果得到了这个。我看到了一些好处,但这是一个相当啰嗦的解决方案。

public class ValueHolder<T> : IDisposable
{
    private readonly Action<T> setter;
    private readonly T oldVal;

    public ValueHolder(Func<T> getter, T tempVal, Action<T> setter)
    {
        this.setter = setter;
        oldVal = getter();
        setter(tempVal);
    }

    public void Dispose()
    {
         setter(oldVal);
    }
}

然后使用如下

public void SomeMethod(){
    using(new ValueHolder<bool>(() => Notifier.DoNotify, false, (b) => Notifier.DoNotify(b)) {

        // Do something ...
    }
}

有什么好的解决方案吗?

(编辑删除了对测试的引用。似乎分散了我想问的内容)

最佳答案

您可以采取一些措施来使其更容易编写。我会尝试利用您正在使用的任何测试框架来帮助在测试之前和之后运行一些设置/清理代码。但除此之外,还有一些可以减少样板的技巧。

首先,我们可以创建一个辅助类,它将减少创建 ValueHolder<T> 的样板文件。实例。我将使用 LINQ 表达式自动创建 getter 和 setter 委托(delegate),而不是要求调用者传递 getter 和 setter(尽管这在高级情况下仍然有用)。

public class ValueHolder
{
    public static ValueHolder<T> Create<T>(Expression<Func<T>> staticProp, T tempVal)
    {
        var ex = (MemberExpression)staticProp.Body;
        var prop = (PropertyInfo)ex.Member;
        var getter = (Func<T>)Delegate.CreateDelegate(typeof(Func<T>), prop.GetGetMethod());
        var setter = (Action<T>)Delegate.CreateDelegate(typeof(Action<T>), prop.GetSetMethod());
        return new ValueHolder<T>(getter, tempVal, setter);
    }
}

这使得创作更加简洁

ValueHolder.Create(() => Notify.DoNotify, false);

其次,您可能需要设置其中一些,而大量使用有点难看。我的answer这个问题提供了一种使用继承自 List<T> 的类以稍微简单的方式处理这种情况的方法。这也是IDisposable 。将这些结合起来,您可以使您的设置变得更加简单:

public void SomeTestMethod()
{
    // before any state has change.

    using (Setup())
    {
          // Test code.
    }

    // the cleanup code has run so the state is reset here.
}

private static IDisposable Setup()
{
    return new DisposableList() {
        ValueHolder.Create(() => Notify.DoNotify, false),
        ValueHolder.Create(() => ConnectionManager.MaxConnections, 100),
        ValueHolder.Create(() => SomeClass.SomeProp, 2.5),
        // etc., I think you get the idea.
    };
}

关于c# - 在 C# 中临时存储和重新设置属性值,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/23949456/

相关文章:

c# - 运行时的 .NET CLR/Framework 检测

c# - 在Windows Azure中使用Redis实现进程外缓存

主要方法的 C# 单元测试 - 操作命令行参数 - Microsoft Visual Studio 测试工具

C# 运行多个查询的最佳方式

c# - 在 WebMatrix 中由 C# 生成选择查询后,在带有空格的列上使用 row.ColumnName

c# - 表达式树是线程安全的吗?

c# - ASP.NET Core API 发送用双引号引起来的字符串

c# - Azure 身份验证 Web 应用本地主机回复 url

c# - ASP.Net Web API 与 WCF,我应该在我的项目中选择哪一个

c# - 文件系统路径和 Directory.Exists()