如何为IDisposable类型使用自定义生成器?

时间:2018-03-05 15:20:47

标签: c# fscheck

请注意:这是关于fscheck的问题,而不是关于C#中IDisposable的一般用法的问题

假设我有以下课程(夸大其词):

public class MyDataTypeWrapper : IDisposable
{
    private MyDataType fMyDataType; // MyDataType implements IDisposable

    public MyDataTypeWrapper(int[] randomData)
    {
         // some conversion routine (not shown)
         var inputToMyDataType = ConvertRandomDataToMyDataInputs(randomData);

         // this could all be done in one method but breaking out into two to illustrate.
         fMyDataType = new MyDataType(inputToMyDataType);
    }

    public void Dispose()
    {
         fMyDataType.Dispose();
    }
}

MyDataType会占用一些非托管资源,因此会实现IDisposableMyDataType类实际上没有构造函数使用int[],因此使用了包装类。

为此创建一个生成器相对简单,但是我无法看到这样的生成器在每次测试迭代后也负责处理创建的对象,这意味着我的测试代码经常被显式调用弄乱到Dispose。请参阅下面的大纲示例。

var generator = from randomData in Arb.Generate<int[]>()
                select new MyDataTypeWrapper(randomData);

// use the generator as input to some fscheck property based tests
Prop.ForAll(generator.ToArbitrary(), (MyDataTypeWrapper randomClassUnderTest) =>
{
    // want to avoid this
    using(randomClassUnderTest)
    {
        // assert some properties
        ...
    }
}).QuickCheckThrowOnFailure();

Prop.ForAll(generator.ToArbitrary(), (MyDataTypeWrapper randomClassUnderTest) =>
{
    // assert some properties
    ...

    // also want to avoid this (equivilant to use of using in example above)
    randomClassUnderTest.Dispose();
}).QuickCheckThrowOnFailure();

任何想法\关于如何避免这种情况的建议将不胜感激。

1 个答案:

答案 0 :(得分:1)

第一个解决方案是相当明显的,但无论如何我会说出来,因为它实际上回答了这个问题:

var generator = from randomData in Arb.Generate<int[]>()
                select new MyDataTypeWrapper(randomData);

Prop.ForAll(generator.ToArbitrary(), (MyDataTypeWrapper randomClassUnderTest) =>
{

   using(randomClassUnderTest)
   {

   }

}).QuickCheckThrowOnFailure();

如果您不想为每个元素执行此操作,则需要创建一些帮助您的方法,例如:

  public static WhateverItReturns DisposablePropAll<TDisposable>(this IEnumerable<TDisposable> elements, Action<TDisposable> action) where TDisposable : IDisposable
        {
            return Prop.ForAll(elements, (TDisposable randomClassUnderTest) =>
            {
                using (randomClassUnderTest)
                {
                    action(randomClassUnderTest);
                }
            });
        }