开发者

How to call delegate only once / one time with moles?

开发者 https://www.devze.com 2023-03-26 00:37 出处:网络
How is it possible to call a delegated Method only once / one time with moles? MyClass.AllInstances.ResultateGet = delegate { return new ResultatInfoColle开发者_如何学Pythonction(); };

How is it possible to call a delegated Method only once / one time with moles?

MyClass.AllInstances.ResultateGet = delegate { return new ResultatInfoColle开发者_如何学Pythonction(); };

I want to call the Method "ResultateGet" only one time because the init is quite complex the first time without a delegate.

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

I am generally interested how to call a moles delegate one time ore a specific number of times before the original function is called and not the delegate.

Update: I found a way, that seems a little bit cumbersome. Any better Solution?

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


Also, see my answer to: How to assign/opt from multiple delegates for a 'moled' method? This provides an example of gating logic inside the anonymous method.

Ooh, good question! I have encountered this, myself. What you are looking for is called a "fallthrough" behavior (execution of the original code). The anonymous method to which Moles detours must contain a switching mechanism that falls through, after the first call. Unfortunately, I don't believe a fallthrough feature is included in Moles, at this time.

Your updated workaround is exactly what you need -- calling fallthrough would do the same thing. I suggest adding a sentinel value, doFallthrough, that gates the calls:

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

Calling a specific number of times simply requires a change to the sentinel value type:

int doFallthrough = 0;
ResultatInfoCollection x = new ResultatInfoCollection();
MyClass.AllInstances.ResultateGet = delegate { 
    if (++doFallthrough < 5)
        return new ResultatInfoCollection();
    MolesContext.ExecuteWithoutMoles(() => x = target.Resultate);
};


Old question, but since I found it when I was searching, I'll answer it for the next person with my solution.

Using MolesContext.ExecuteWithoutMoles to call the original function works just fine in most cases, however, if you are moling any other functions or classes downstream from this call, they won't be moled, either.

Given the following class:

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

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

If you use the MolesContext.ExecuteWithoutMoles approach:

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;
};

Your mole for OtherFunction will not be hit, because it was (indirectly) executed within the "without moles" scope.

However, you can add and remove moles delegates at any time, so that allows you to do the following, as outlined in the Moles Documentation (p. 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;

The OtherFunction moles is still hit. With this method, you can remove moling just from the specific method without impacting your other moles. I've used this, and it works. The only trouble I can see is that it won't work if you have a recursive function, or possibly a multi-threaded situation.

0

精彩评论

暂无评论...
验证码 换一张
取 消

关注公众号