问题
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:
- Some+Shortcut
SomeClass
ServiceA
ServiceB
- 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:
- Invoke the
ctor
code snippet. - Fill in the constructor body.
- 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.
回答1:
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$)
来源:https://stackoverflow.com/questions/20154790/how-can-i-automatically-generate-a-constructor-that-receives-and-stores-services