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

C# 在C中临时存储和重新设置属性值#,c#,C#,当我在一个特定的代码库中编写测试时,我经常需要在我新添加的代码之前设置一个static属性,并在离开时重新设置它。范例 public void SomeMethod(){ val oldVal = Notifier.DoNotify; Notifier.DoNotify = false; // Some code... Notifier.DoNotify = oldVal; } 我认为这种方式很难看,我想要更好的东西,这也让我很难忘记重新设置值 我试着做了点

当我在一个特定的代码库中编写测试时,我经常需要在我新添加的代码之前设置一个static属性,并在离开时重新设置它。范例

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);
    }
}
公共类价值持有人:IDisposable
{
私有只读操作设置器;
私有只读T oldVal;
公共估价师(职能获取者、临时估价师、行动制定者)
{
this.setter=setter;
oldVal=getter();
setter(tempVal);
}
公共空间处置()
{
塞特(奥尔德瓦尔);
}
}
那么它的用法是

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

        // Do something ...
    }
}
public void SomeMethod(){
使用(新的估价师(()=>Notifier.DoNotify,false,(b)=>Notifier.DoNotify(b)){
//做点什么。。。
}
}
解决这个问题的好办法是什么


Edit删除了对测试的引用。似乎分散了我的注意力)您可以做几件事来简化编写。我会尝试利用您正在使用的任何测试框架来帮助在测试前后运行一些设置/清理代码。但除此之外,还有一些技巧可以减少工作量

首先,我们可以创建一个helper类,它将在创建
ValueHolder
实例的样板文件中减少一点工作量。我将使用LINQ表达式自动创建getter和setter委托,而不需要在getter和setter中同时使用调用方传递(尽管在高级情况下这仍然很有用)

其次,您可能需要设置其中的一些,而大使用有点难看。我对这个问题的回答提供了一种方法,使用从
List
继承的类来处理这种情况,该类也是
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.
    };
}

您最好希望您的测试不要并行运行…也许更适合此类问题的站点您使用的测试框架是什么?通常有一种方法可以在测试方法之前和之后运行一些代码。这显然比手动重置值要好。我会更改类的名称,以关注其重置行为h、 谢谢你的评论!虽然我不是在寻找如何使用测试框架来解决这个问题。我很精通单元测试,但现在更感兴趣的是学习C#我喜欢使用列表的想法。使用Linq似乎有点贵?@peter表达式树和反射比lambdas贵,但我怀疑它是否贵大量的时间。在数百纳秒而不是几十纳秒的数量级上。除非您对测试有非常严格的性能要求,否则您不会注意到这一点。谢谢!您可能是对的。(性能始终很重要-我关心用户笔记本电脑的电池寿命。我删除了对测试的引用:-)尽管如此,即使是测试,我也关心性能。)
ValueHolder.Create(() => Notify.DoNotify, false);
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.
    };
}