开发者

Resharper (or Visual Studio) shortcut to cascade changes to a constructor

Here is a common refactoring that I don't believe I have seen a shortcut for:

Imagine we have a base class with a number of inheriting subclasses. The base classes uses constructor injection to accept a number of services:

class FooBase
{
    private IMyService _myService;
    private IMyOtherService _myOtherService;

    public FooBase(IMyService myService, IMyOtherService _myOtherService)
    {
         _myService = myService;
         _myOtherService = myOtherService;
    }
}

class FooConcrete : FooBase
{
    public FooConcrete(IMyService myService, IMyOtherService _myOtherService)
        base(myService, myOtherService)
    {
    }
}

Notice how FooConcrete has to call the constructor of its base class, FooBase.

Now, what happens if I want to add another service to FooBase? I can quickly initialize the new private field from FooBase's constructor. But I still have to go around and manually update every subclass that inherits from FooBase. This can be a hassle if there are lots of inheriting classes.

Is there a shortcut, or perhaps a trick that I can use, to quickly update all t开发者_Python百科he subclasses' constructors as well?


Since I asked this question Resharper have now added support as part of the Change Signature feature.

For example, to add a parameter to a constructor in the base class, use the following method:

  1. Right click on the constructor you want to change, select Refactor->Change Signature.

  2. Make the changes you require and click Next. Select "Resolve with call tree" and click Next.

  3. Your change will be made, and a window will open somewhere in Visual Studio titled "Refactoring - Change signature". A list of inheriting classes will be shown in this window.

  4. Double click on each of the classes and choose the "Create parameter x in constructor y"


Build, then Fix compilation errors.

ReSharper has no tool for this, including AFAIK in ReSharper 6, which got launched today.


Default Value in Change Signature

The best way I know is to add new service parameter to FooBase constructor by Change Signature (Ctrl+R,S) with a proper parameter name as default value, e.g. yetAnotherService.

After that you have indeed errors in base calls in all sub class constructors. But you can fix every error by only 3 key strokes:
- go to error by Alt+Shift+Page Down,
- open context menu by Alt+Enter,
- select first option (Create parameter 'yetAnotherService' in containing constructor) by Enter.

Ok you still have many key strokes. But it's the fastest way (with ReSharper 5.1.3) I know.


Parameter class by ReSharper refactoring

If you know that constructors can change through the lifetime you could create a parameter class like:

class FooInfo
{
    IMyService MyService {get; set;}
    IMyOtherService MyOtherService {get; set;}
}

and can pass such an object to constructor, i.e:

class FooBase
{
    private FooInfo _fooInfo;

    public FooBase(FooInfo fooInfo)
    {
         _fooInfo= fooInfo;
    }
}

class FooConcrete : FooBase
{
    public FooConcrete(FooInfo fooInfo)
        base(fooInfo)
    {
    }
}

Then if you need a new parameter you just add it to FooInfo class. Changes in subclasses are not needed.

ReSharper has a refactoring for generating such a parameter class from constructor parameters:
Place cursor on constructor name in code file and
press Ctrl+Shift+R and
select Extract Class From Parameters....

0

上一篇:

下一篇:

精彩评论

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

最新问答

问答排行榜