Как позвонить делегату только один раз / один раз с родинками? - PullRequest
1 голос
/ 04 августа 2011

Как можно вызвать делегированный метод только один раз / один раз с родинками?

MyClass.AllInstances.ResultateGet = delegate { return new ResultatInfoCollection(); };

Я хочу вызывать метод "ResultateGet" только один раз, потому что инициализация довольно сложна в первый раз без делегата.

target.UpdateResultate(); //calls delegate "ResultateGet"
//Assert some stuff
target.Verify(); //needs original function "ResultateGet" so unit test is useful

Меня, как правило, интересует, как один раз вызвать делегат крота или определенное количество раз, прежде чем вызывается исходная функция, а не делегат.

Обновление: Я нашел способ, который кажется немного громоздким. Есть лучшее решение?

ResultatInfoCollection x = new ResultatInfoCollection();
MolesContext.ExecuteWithoutMoles(() => x = target.Resultate);

Ответы [ 2 ]

2 голосов
/ 05 августа 2011

Кроме того, см. Мой ответ на: Как назначить / выбрать несколько делегатов для метода "moled"? Это обеспечивает пример логики стробирования внутри анонимногоmethod.

О, хороший вопрос!Я столкнулся с этим сам.То, что вы ищете, называется поведением «падения» (выполнение исходного кода).Анонимный метод, к которому обходы Moles должны содержать механизм переключения, который проваливается после первого вызова.К сожалению, я не верю, что в Moles в это время включена функция прорыва.

Ваш обновленный обходной путь - именно то, что вам нужно - вызов fallthrough сделал бы то же самое.Я предлагаю добавить значение дозорного, doFallthrough , которое стробирует вызовы:

bool doFallthrough = false;
ResultatInfoCollection x = new ResultatInfoCollection();
MyClass.AllInstances.ResultateGet = delegate { 
    if (!doFallthrough)
    {
        doFallthrough = true;
        return new ResultatInfoCollection();
    }
    MolesContext.ExecuteWithoutMoles(() => x = target.Resultate);
};

Вызов определенного количества раз просто требует изменения типа значения дозорного:

int doFallthrough = 0;
ResultatInfoCollection x = new ResultatInfoCollection();
MyClass.AllInstances.ResultateGet = delegate { 
    if (++doFallthrough < 5)
        return new ResultatInfoCollection();
    MolesContext.ExecuteWithoutMoles(() => x = target.Resultate);
};
0 голосов
/ 08 ноября 2013

Старый вопрос, но так как я нашел его, когда искал, я отвечу на него следующему человеку с моим решением.

Использование MolesContext.ExecuteWithoutMoles для вызова исходной функции в большинстве случаев работает просто отлично, однако, если вы вызываете другие функции или классы ниже по потоку от этого вызова, они также не будут смоделированы.

Дан следующий класс:

public class TheClass
{
    public int TheFunction(int input){
        return input + TheOtherFunction();
    }

    public int TheOtherFunction(){
        return DateTime.Now.Minutes;
    }
}

Если вы используете MolesContext.ExecuteWithoutMoles подход:

MTheClass.AllInstances.TheOtherFunctionInt = (instance) => {
    return 5;
};

MTheClass.AllInstances.TheFunctionInt = (instance, input) =>
{
    //do your stuff here, for example:
    Debug.WriteLine(input.ToString());

    var result = MolesContext.ExecuteWithoutMoles<int>(() => instance.TheFunction(input));

    //do more stuff, if desired    
    return result;
};

Ваш моль для OtherFunction не будет поражен, потому что он (косвенно) был выполнен в области действия "без родинок".

Однако вы можете добавлять и удалять делегатов родинок в любое время, что позволяет вам делать следующее, как описано в Документация родинок (стр. 24)

MTheClass.AllInstances.TheOtherFunctionInt = (instance) => {
    return 5;
};

MolesDelegates.Func<TheClass, int, int> molesDelegate = null;
molesDelegate = (instance, input) =>
{
    //do your stuff here, for example:
    Debug.WriteLine(input.ToString());

    int result = 0;
    try{
        MTheClass.AllInstances.TheFunctionInt = null;
        result = instance.TheFunction(input);
    }
    finally{
        MTheClass.AllInstances.TheFunctionInt = molesDelegate;
    }

    //do more stuff, if desired

    return result;
};

MTheClass.AllInstances.TheFunctionInt = molesDelegate;

Кроты OtherFunction все еще поражены. С помощью этого метода вы можете удалить молдинг только с определенного метода, не влияя на другие родинки. Я использовал это, и это работает. Единственная проблема, которую я вижу, это то, что она не будет работать, если у вас есть рекурсивная функция или, возможно, многопоточная ситуация.

...