How can I automatically generate a constructor that receives and stores services for free?
Asked Answered
M

1

1

Problem

I regularly find myself manually typing out code that looks like this:

public class SomeClass
{
    readonly ServiceA serviceA;
    readonly ServiceB serviceB;

    public SomeClass(ServiceA serviceA, ServiceB serviceB)
    {
        this.serviceA = serviceA.;
        this.serviceB = serviceB;
    }
}

Requirements

I would like to save time by having a way to generate as much of this as possible. I don't want to use a tool that requires a purchase. The only information that is variable here is the class name and the types of the services. So in this example, I would like to be to type something minimal like this:

  1. Some+Shortcut
  2. SomeClass
  3. ServiceA
  4. ServiceB
  5. Enter

I'm also open to a solution that still requires me to type in the names of the fields. I don't mind whether or not the private access modifier is present in the field definitions, although I prefer to not have it since the code is a bit leaner that way. Similarly, I'm willing to accept a solution that doesn't generate read-only fields, but I do prefer them since I seldom want to change a service after my class is initialised.

What I've Tried

The quickest solution I know of at the moment is to type something like the following in another section of code and tell Visual Studio to create the class and constructor from its usage.

new SomeClass((ServiceA)null, (ServiceB)null);

However, I don't always work in this order; sometimes I want to create a class before using it. So what I typically do is this:

  1. Invoke the ctor code snippet.
  2. Fill in the constructor body.
  3. Use CodeRush Xpress to generate the fields. (It provides a way to generate read-only fields, whereas Visual Studio doesn't make them read-only.)

Code-snippets work well, but I don't think they support variable numbers of parameters, so they're probably not suited to this problem.

Mitigate answered 22/11, 2013 at 21:27 Comment(10)
Code snippet, but have a version for 1-N constructors. Call them class1, class2, etc.Blandishment
If all your code follows a similar pattern, you could easily create a simple app that can output a file based on some input names. Might also be possible to do it as visual studio templates (just like xml, html, c# class etc)Offenbach
Free version of CodeRush maybe a option.Wilhoit
@TGH, what sort of workflow would you suggest? Use of an external program to provide a global keyboard shortcut to this program? I would prefer something that integrates with the IDE.Mitigate
@N4TKD, which of its features provides this function? I couldn't find one that would help, besides the one that I already mentioned in the question.Mitigate
@Mitigate templates I believe in the free version you can still add your own, in the paid version I know you can but I believe I made some before I paid the full version.Wilhoit
Resharper does just that with Alt+Inst. All of this takes 1sec with keyboard shortcuts. R# is worth a purchase. Although you could use the trial in a VM that you reset every month...Misdeem
@usr, I agree that tools like ReSharper are worth the purchase, but for personal development, it's too expensive, and for commercial use, I wouldn't expect my employer would be willing to pay. And I'm not willing to abuse trial software.Mitigate
@Mitigate An external app would probably me the last resort. I was thinking in terms of creating file type templates - akin to the already existing ones like xml, c#, DataSet ++Offenbach
@N4TKD, I just investigated CodeRush templates, and it looks like they're only available in the paid version.Mitigate
P
4

Go to your default C# code snippets location, usually in C:\Program Files (x86)\Microsoft Visual Studio 10.0\VC#\Snippets\1033\Visual C# and make a copy of ctor.snippet into your personal code snippets location, rename it, and give it a proper name and shortcut key. Then change the declaration (look at other existing ones), something like the below can do the job. Once you create it, you can simply type svc + TAB (or whatever shortcut you choose then tab) in an empty class file, and you should get the content filled up, alternatively you may be able to customize a class template so when you do add new, you can select your new template.

<?xml version="1.0" encoding="utf-8" ?>
<CodeSnippets  xmlns="http://schemas.microsoft.com/VisualStudio/2005/CodeSnippet">
    <CodeSnippet Format="1.0.0">
        <Header>
            <Title>Some Constructor</Title>
            <Shortcut>svc</Shortcut>
            <Description>my description</Description>
            <Author>Jason was here</Author>
            <SnippetTypes>
                <SnippetType>Expansion</SnippetType>
            </SnippetTypes>
        </Header>
        <Snippet>
            <Declarations>
                <Literal>
                    <ID>accessor</ID>
                    <ToolTip>Access modifier</ToolTip>
                    <Default>public</Default>
                </Literal>
                <Literal Editable="false">
                    <ID>classname</ID>
                    <ToolTip>Class name</ToolTip>
                    <Function>ClassName()</Function>
                    <Default>ClassNamePlaceholder</Default>
                </Literal>
                <Literal Editable="true">
                    <ID>svcA</ID>
                    <ToolTip>Service A</ToolTip>
                    <Default>ServiceA</Default>
                </Literal>
                <Literal Editable="true">
                    <ID>svcAvar</ID>
                    <ToolTip>Service A</ToolTip>
                    <Default>serviceA</Default>
                </Literal>
                <Literal Editable="true">
                    <ID>svcB</ID>
                    <ToolTip>Service B</ToolTip>
                    <Default>ServiceB</Default>
                </Literal>
                <Literal Editable="true">
                    <ID>svcBvar</ID>
                    <ToolTip>Service B</ToolTip>
                    <Default>serviceB</Default>
                </Literal>
            </Declarations>
            <Code Language="csharp"><![CDATA[readonly $svcA$ $svcAvar$;
    readonly $svcB$ $svcBvar$;

    $accessor$ $classname$ ($svcA$ serviceA, $svcB$ serviceB)
    {
        this.$svcAvar$ = serviceA;
        this.$svcBvar$ = serviceB
    }$end$]]>
            </Code>
        </Snippet>
    </CodeSnippet>
</CodeSnippets>

In the above we declare variables for the classes svcA = ServiceA, svcB = ServiceB, and the class variables svcAvar = serviceA and svcBvar = serviceB, so we can easily modify in one location, you can create more for the params in the constructor, etc, but should be enough to get you started.

Regarding the variable number of params, you can use the default params literal which would then let you type whatever params you need after you insert the ctor, if you have varying class level variables, then just like others have said, create several snippets with different shortcuts, like svc, svc1, svc2, svc3 etc

<Literal>
    <ID>params</ID>
    <ToolTip>Parameter list</ToolTip>
    <Default></Default>
</Literal>

then ...<![CDATA[$accessor$ $classname$ (...$params$)

Peppergrass answered 22/11, 2013 at 22:13 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.