tonerdo / pose

Replace any .NET method (including static and non-virtual) with a delegate
MIT License
1.08k stars 74 forks source link

Ignore methods during isolation #28

Open dtkujawski opened 6 years ago

dtkujawski commented 6 years ago

I was having an issue with calling a certain static method which called other methods downstream (one of which was LINQ and EntityFramework) where using Pose.Isolate(...) it would fail.

My basic question is: is there a way I can tell it to not traverse through a certain method call recursively (short-circuit it)

I took the source and made a simple/hack way to do this that works, but wondering if there is a way without customizing the source:

    PoseContext.Ignore(@"^System\.");
    Shim shimCheckVal = Shim.Replace(() => CheckVal(Is.A<int>())).With((Func<int, int>)(x => { return 2; }));
    PoseContext.Isolate(() =>
    {
        person = Fetch(id);
    }, shimCheckVal);

In this example, I am using a regex pattern to ignore any method in the System namespace.

To make this work, I just changed the EmitILForMethod implementation and added the check at the top:

        private void EmitILForMethod(ILGenerator ilGenerator, Instruction instruction, MemberInfo memberInfo)
        {
            if (PoseContext.CheckIgnore($"{memberInfo.DeclaringType.FullName}.{memberInfo.Name}"))
            {
                ilGenerator.Emit(instruction.OpCode, memberInfo as MethodInfo);
                return;
            }
            ...

The PoseContext class just has some methods for setting up the ignore patterns and checking them:

        internal static List<Regex> Ignores { private set; get; } = new List<Regex>();

        public static void IgnoreClear()
        {
            Ignores.Clear();
        }

        public static void Ignore(string pattern)
        {
            if (string.IsNullOrEmpty(pattern))
            {
                throw new ArgumentNullException(nameof(pattern));
            }
            Ignores.Add(new Regex(pattern, RegexOptions.IgnoreCase | RegexOptions.Compiled));
        }

        public static bool CheckIgnore(string value)
        {
            foreach (var ignore in Ignores)
            {
                if (ignore.IsMatch(value))
                {
                    return true;
                }
            }
            return false;
        }
tonerdo commented 6 years ago

Hi @dtkujawski, Pose doesn't support ignoring methods. Will consider including this feature in the next major release

hybridherbst commented 5 years ago

When is the next major release to be expected? :)