orcun
orcun

Reputation: 14979

Replacing all usages of a method (Introduce Indirection)

I am generally not very fond of refactoring tools. No need to get into details. Still, I occasionally try out new versions. Here is what I was trying to do while evaluating resharper 4.5 :

I needed to replace all usages of a method with a wrapper method (to be created) but I could not. I usually suck at noticing an obvious feature, is this the case? If resharper does not have this feature, do you know such tools?

Edit 2: Sample has been improved to include instance method calls. Edit: Here is a simple case to play.

    static void Main(string[] args)
    {
        while(true)
        {
            if (Console.ReadKey().Key == ConsoleKey.Escape)
            {
                Thread.Sleep(10);
                if (Quiting()) break;
            }
            Console.Beep(250, 50);
        }
    }

    static bool Quiting()
    {
        if (Console.In.Peek() > 0)
        {
            Console.Beep(250, 150);
            return false;
        }
        return true;
    }

What I need is something like: (Edit2: added an instance sample)

    private static StringBuilder _builder = new StringBuilder();

    static void Main(string[] args)
    {
        while(true)
        {
            var key = Console.ReadKey();
            if (key.Key == ConsoleKey.Escape)
            {
                Thread.Sleep(10);
                if (Quiting()) break;
            }
            _builder.Append(" (").Append(key.KeyChar).Append(") ");
            Beep(250, 50);
        }
    }

    static bool Quiting()
    {
        if (Console.In.Peek() > 0)
        {
            Beep(250, 150);
            _builder.Append('@');
            return false;
        }
        return true;
    }

    static void Beep(int frequency, int duration)
    {
        // finally cursor ends up here
        Console.Beep(250, 50);
    }

Console.Beep calls are refactored. Next lets refactor StringBuilder.Append(char) :

class Program
{
    private static StringBuilder _builder = new StringBuilder();

    static void Main(string[] args)
    {
        while(true)
        {
            var key = Console.ReadKey();
            if (key.Key == ConsoleKey.Escape)
            {
                Thread.Sleep(10);
                if (Quiting()) break;
            }
            _builder.Append(" (").AppendUpper(key.KeyChar).Append(") ");
            Beep(250, 50);
        }
    }

    static bool Quiting()
    {
        if (Console.In.Peek() > 0)
        {
            Beep(250, 150);
            _builder.AppendUpper('n');
            return false;
        }
        return true;
    }

    static void Beep(int frequency, int duration)
    {
        // finally cursor ends up here
        Console.Beep(250, 50);
    }
}

static class StringBuilderExtensions
{
    public static StringBuilder AppendUpper(this StringBuilder builder, char c)
    {
        return builder.Append(char.ToUpper(c));
    }
}

Selecting from usages and maybe omitting common parameters (such as 250 above) or common instance parameters for non-extension statics shall make this feature more valuable. Hopefully, this clears up the question.

Upvotes: 2

Views: 1700

Answers (4)

Craig Curtis
Craig Curtis

Reputation: 863

Resharper has a Search and Replace with Pattern feature. It can search and replace on patterns and expressions.

This would refactor all calls to Console.Beep() to your own method. It only replaces the usage if 250 is the first parameter:

Reaplace call to Console.Beep()

However this would replace the usage of Console.Beep() within your own Beep method. You would have to manually replace that one usage.

Upvotes: 0

Martin Harris
Martin Harris

Reputation: 28617

Assuming the wrapper method will be in the same class you can rename the current method to the name of the new wrapper method (ctrl+R+R in Resharper). This will rename all calls to this method in the solution as well. Then rename the original method back by hand (don't use Resharper or all the calls will get renamed back too) and add the wrapper method.


Based on your edit I think you will be out of luck to get the functionality that you want from any Visual Studio add-in that I've seen (beyond the simple find and replace which will get you some of the way there I guess).

Depending on how much time and effort you are willing to devote to this I'd imagine it's possible to use the DXCore framework and write a plugin that will do this kind of refactoring.

Upvotes: 3

John Saunders
John Saunders

Reputation: 161773

ReSharper doesn't have this as a single refactoring. I might do it as follows:

  1. Select the contents of the method to be wrapped, and use Extract Method to create a new private method from the contents.
  2. The original method is now a trivial wrapper around "itself". Rename it if you like, or manipulate it as you like (make it static, move to a different class, surround with try/catch, whatever).

EDIT: Based on your edit, it seems you have an additional problem. Not only is Console.Beep not in the same class, it's not even in your class.

But if you don't mind a little search and replace, then you can put it into your own class, then proceed with the refactoring:

namespace Temporary {
    public class Console {
        public static void Beep(int x, int y) {System.Console.Beep(x,y);}
    }
}

Then do a "Replace in Files" to replace Console.Beep with Temporary.Console.Beep, and proceed as above.

Upvotes: 5

Frans Bouma
Frans Bouma

Reputation: 8357

It's not included in any .NET refactoring IIRC, the tool which has such a refactoring is Eclipse, but not for .NET/C#

Upvotes: 4

Related Questions