Eli*_*jah 152 c# resharper code-generation visual-studio-2010 visual-studio
我已经习惯了许多Java IDE(Eclipse,Netbeans,IntelliJ),为您提供了一个命令,可以根据类中的字段为类生成默认构造函数.
例如:
public class Example
{
public decimal MyNumber { get; set; }
public string Description { get; set; }
public int SomeInteger { get; set; }
// ??? This is what I want generated ???
public Example(decimal myNumber, string description, int someInteger)
{
MyNumber = myNumber;
Description = description;
SomeInteger = someInteger;
}
}
Run Code Online (Sandbox Code Playgroud)
在大多数OOP语言中,让构造函数填充对象的所有字段是一项常见任务,我假设有一些方法可以节省在C#中编写此样板代码的时间.我是C#世界的新手,所以我想知道我是否遗漏了一些关于语言的基本信息?Visual Studio中有一些明显的选项吗?
Pou*_*mie 160
在visual studio 2015 Update3中,我有这个功能.
只需突出显示属性,然后按ctrl + . 然后按Generate Constructor.
例如,如果您突出显示了2个属性,则建议您创建一个包含2个参数的构造函数,如果您选择了3,则会建议使用3个参数,依此类推.
也适用于VS2017.
Jam*_*ack 122
Resharper提供了一个Generate Constructor工具,您可以在其中选择要初始化的任何字段/属性.我使用Alt+ Ins热键来访问它.
Jar*_*Par 29
C#在Visual Studio 2010中添加了一项名为generate from usage的新功能.目的是从使用模式生成标准代码.其中一个特性是基于初始化模式生成构造函数.
可以通过智能标签访问该功能,该标签将在检测到模式时显示.
例如.可以说我有以下课程
class MyType {
}
Run Code Online (Sandbox Code Playgroud)
我在我的申请中写了以下内容
var v1 = new MyType(42);
Run Code Online (Sandbox Code Playgroud)
采用int不存在的构造函数将显示一个智能标记,其中一个选项将是"生成构造函数存根".选择它将修改代码为MyType以下内容.
class MyType {
private int p;
public MyType(int p) {
// TODO: Complete member initialization
this.p = p;
}
}
Run Code Online (Sandbox Code Playgroud)
JMa*_*sch 15
您可以编写一个宏来执行此操作 - 您将使用Visual Studio的解析器来检索有关该类成员的信息.
我写了一个类似的宏.(我将在下面分享代码).我写的宏是为了在你从它继承时复制基类中的所有构造函数(对于类似于在ctor上有很多重载的异常这样的类很有用).
这是我的宏(再次,它不能解决你的问题,但你可以修改为你想要的)
Imports System
Imports EnvDTE
Imports EnvDTE80
Imports EnvDTE90
Imports EnvDTE100
Imports System.Diagnostics
Public Module ConstructorEditor
Public Sub StubConstructors()
'adds stubs for all of the constructors in the current class's base class
Dim selection As TextSelection = DTE.ActiveDocument.Selection
Dim classInfo As CodeClass2 = GetClassElement()
If classInfo Is Nothing Then
System.Windows.Forms.MessageBox.Show("No class was found surrounding the cursor. Make sure that this file compiles and try again.", "Error")
Return
End If
If classInfo.Bases.Count = 0 Then
System.Windows.Forms.MessageBox.Show("No parent class was found for this class. Make sure that this file, and any file containing parent classes compiles and try again")
Return
End If
'setting up an undo context -- one ctrl+z undoes everything
Dim closeUndoContext As Boolean = False
If DTE.UndoContext.IsOpen = False Then
closeUndoContext = True
DTE.UndoContext.Open("StubConstructorsContext", False)
End If
Try
Dim parentInfo As CodeClass2 = classInfo.Bases.Item(1)
Dim childConstructors As System.Collections.Generic.List(Of CodeFunction2) = GetConstructors(classInfo)
Dim parentConstructors As System.Collections.Generic.List(Of CodeFunction2) = GetConstructors(parentInfo)
For Each constructor As CodeFunction2 In parentConstructors
If Not MatchingSignatureExists(constructor, childConstructors) Then
' we only want to create ctor stubs for ctors that are missing
' note: a dictionary could be more efficient, but I doubt most classes will have more than 4 or 5 ctors...
StubConstructor(classInfo, constructor)
End If
Next
Finally
If closeUndoContext Then
DTE.UndoContext.Close()
End If
End Try
End Sub
Private Function GetConstructors(ByVal classInfo As CodeClass2) As System.Collections.Generic.List(Of CodeFunction2)
' return a list of all of the constructors in the specified class
Dim result As System.Collections.Generic.List(Of CodeFunction2) = New System.Collections.Generic.List(Of CodeFunction2)
Dim func As CodeFunction2
For Each member As CodeElement2 In classInfo.Members
' members collection has all class members. filter out just the function members, and then of the functions, grab just the ctors
func = TryCast(member, CodeFunction2)
If func Is Nothing Then Continue For
If func.FunctionKind = vsCMFunction.vsCMFunctionConstructor Then
result.Add(func)
End If
Next
Return result
End Function
Private Function MatchingSignatureExists(ByVal searchFunction As CodeFunction2, ByVal functions As System.Collections.Generic.List(Of CodeFunction2)) As Boolean
' given a function (searchFunction), searches a list of functions where the function signatures (not necessarily the names) match
' return null if no match is found, otherwise returns first match
For Each func As CodeFunction In functions
If func.Parameters.Count <> searchFunction.Parameters.Count Then Continue For
Dim searchParam As CodeParameter2
Dim funcParam As CodeParameter2
Dim match As Boolean = True
For count As Integer = 1 To searchFunction.Parameters.Count
searchParam = searchFunction.Parameters.Item(count)
funcParam = func.Parameters.Item(count)
If searchParam.Type.AsFullName <> funcParam.Type.AsFullName Then
match = False
Exit For
End If
Next
If match Then
Return True
End If
Next
' no match found
Return False
End Function
Private Sub StubConstructor(ByVal classInfo As CodeClass2, ByVal parentConstructor As CodeFunction2)
' adds a constructor to the current class, based upon the parentConstructor that is passed in
' highly inefficient hack to position the ctor where I want it (after the last ctor in the class, if there is another ctor
' note that passing zero as the position (put the ctor first) caused some problems when we were adding ctors to classes that already had ctors
Dim position As Object
Dim ctors As System.Collections.Generic.List(Of CodeFunction2) = GetConstructors(classInfo)
If ctors.Count = 0 Then
position = 0
Else
position = ctors.Item(ctors.Count - 1)
End If
' if there are no other ctors, put this one at the top
Dim ctor As CodeFunction2 = classInfo.AddFunction(classInfo.Name, vsCMFunction.vsCMFunctionConstructor, vsCMTypeRef.vsCMTypeRefVoid, position, parentConstructor.Access)
Dim baseCall As String = ":base("
Dim separator As String = ""
For Each parameter As CodeParameter2 In parentConstructor.Parameters
ctor.AddParameter(parameter.Name, parameter.Type, -1)
baseCall += separator + parameter.Name
separator = ", "
Next
baseCall += ")"
' and 1 sad hack -- appears to be no way to programmatically add the :base() calls without using direct string manipulation
Dim startPoint As TextPoint = ctor.GetStartPoint()
Dim endOfSignature As EditPoint = startPoint.CreateEditPoint()
endOfSignature.EndOfLine()
endOfSignature.Insert(baseCall)
startPoint.CreateEditPoint().SmartFormat(endOfSignature)
End Sub
Private Function GetClassElement() As CodeClass2
'returns a CodeClass2 element representing the class that the cursor is within, or null if there is no class
Try
Dim selection As TextSelection = DTE.ActiveDocument.Selection
Dim fileCodeModel As FileCodeModel2 = DTE.ActiveDocument.ProjectItem.FileCodeModel
Dim element As CodeElement2 = fileCodeModel.CodeElementFromPoint(selection.TopPoint, vsCMElement.vsCMElementClass)
Return element
Catch
Return Nothing
End Try
End Function
End Module
Ant*_*bry 11
这是我用于此目的的宏.它将从具有私有setter的字段和属性生成构造函数.
Imports System
Imports EnvDTE
Imports EnvDTE80
Imports EnvDTE90
Imports EnvDTE90a
Imports EnvDTE100
Imports System.Diagnostics
Imports System.Collections.Generic
Public Module Temp
Sub AddConstructorFromFields()
DTE.UndoContext.Open("Add constructor from fields")
Dim classElement As CodeClass, index As Integer
GetClassAndInsertionIndex(classElement, index)
Dim constructor As CodeFunction
constructor = classElement.AddFunction(classElement.Name, vsCMFunction.vsCMFunctionConstructor, vsCMTypeRef.vsCMTypeRefVoid, index, vsCMAccess.vsCMAccessPublic)
Dim visitedNames As New Dictionary(Of String, String)
Dim element As CodeElement, parameterPosition As Integer, isFirst As Boolean = True
For Each element In classElement.Children
Dim fieldType As String
Dim fieldName As String
Dim parameterName As String
Select Case element.Kind
Case vsCMElement.vsCMElementVariable
Dim field As CodeVariable = CType(element, CodeVariable)
fieldType = field.Type.AsString
fieldName = field.Name
parameterName = field.Name.TrimStart("_".ToCharArray())
Case vsCMElement.vsCMElementProperty
Dim field As CodeProperty = CType(element, CodeProperty)
If field.Setter.Access = vsCMAccess.vsCMAccessPrivate Then
fieldType = field.Type.AsString
fieldName = field.Name
parameterName = field.Name.Substring(0, 1).ToLower() + field.Name.Substring(1)
End If
End Select
If Not String.IsNullOrEmpty(parameterName) And Not visitedNames.ContainsKey(parameterName) Then
visitedNames.Add(parameterName, parameterName)
constructor.AddParameter(parameterName, fieldType, parameterPosition)
Dim endPoint As EditPoint
endPoint = constructor.EndPoint.CreateEditPoint()
endPoint.LineUp()
endPoint.EndOfLine()
If Not isFirst Then
endPoint.Insert(Environment.NewLine)
Else
isFirst = False
End If
endPoint.Insert(String.Format(MemberAssignmentFormat(constructor.Language), fieldName, parameterName))
parameterPosition = parameterPosition + 1
End If
Next
DTE.UndoContext.Close()
Try
' This command fails sometimes '
DTE.ExecuteCommand("Edit.FormatDocument")
Catch ex As Exception
End Try
End Sub
Private Sub GetClassAndInsertionIndex(ByRef classElement As CodeClass, ByRef index As Integer, Optional ByVal useStartIndex As Boolean = False)
Dim selection As TextSelection
selection = CType(DTE.ActiveDocument.Selection, TextSelection)
classElement = CType(selection.ActivePoint.CodeElement(vsCMElement.vsCMElementClass), CodeClass)
Dim childElement As CodeElement
index = 0
For Each childElement In classElement.Children
Dim childOffset As Integer
childOffset = childElement.GetStartPoint(vsCMPart.vsCMPartWholeWithAttributes).AbsoluteCharOffset
If selection.ActivePoint.AbsoluteCharOffset < childOffset Or useStartIndex Then
Exit For
End If
index = index + 1
Next
End Sub
Private ReadOnly Property MemberAssignmentFormat(ByVal language As String) As String
Get
Select Case language
Case CodeModelLanguageConstants.vsCMLanguageCSharp
Return "this.{0} = {1};"
Case CodeModelLanguageConstants.vsCMLanguageVB
Return "Me.{0} = {1}"
Case Else
Return ""
End Select
End Get
End Property
End Module
Run Code Online (Sandbox Code Playgroud)
我意识到这是一个古老的问题,但如果有人还在寻找它,你可以使用Resharper 8+轻松完成.的ctorf,ctorp和ctorfp片段生成填充所有字段,属性或字段和类的属性构造函数.
| 归档时间: |
|
| 查看次数: |
131570 次 |
| 最近记录: |