2011-06-10 53 views
3

我有很多屬性的類,我想知道有什麼方法可以讓Visual Studio,Resharper或其他工具在創建對象時創建調用屬性的語法。所以我不需要通過我自己的所有屬性,只需設置價值,就是這樣。像這樣的東西。創建對象時自動生成屬性

Object foo = new Object{ 
    prop1 = , 
    prop2 = , 
    prop3 = }; 

我不知道人們是否理解這個問題。我希望Visual Studio在創建對象時爲該屬性創建setter。不是財產本身。

+0

即使是一個小工具來自動創建一個構造函數採取所有的參數將是偉大的。一些O/R映射器實際上創建了一個構造器,它可以獲取所有的參數來填充所有的屬性,對於簡單的對象可能會有所幫助。 – CodingBarfield 2011-06-10 07:54:49

回答

0

您可以使用anonimous對象:具有屬性onetwothree

0

不智能感知做的最對你的工作呢

var foo = new { one = 1, two = 2, three = 3}; 

在這種情況下,將創建新的對象?通常情況下,只要您打開{新聞空間,它應該爲您提供所有屬性的列表。

+0

是的,但是當它們有很多的時候,你會自動想要它們;)。 – TuomasK 2011-06-10 07:56:56

1

編輯 誤解了這個問題

我有一個宏,從這個行

MyClass x = new MyClass(); 

產生

x.StrProp = "string"; 
x.IntProp = 0; 

我用它來生成測試代碼,但你可以改變PrintMemberAssignment功能呈現的結果,只要你喜歡:

宏看起來像這樣(把它分配給一個鍵盤快捷鍵)

Private mUsings As New HashSet(Of String) 

Sub InitializeAllMembers() 
    Try 
     Dim assignmentPattern As New Regex("(?<Indent>\s*)(?:(?<DeclaredType>\S+)\s+)?(?<VariableName>[\S=]+)\s*=\s*(?<new>new)?\s*(?<CreatedType>[^\s\(]+)") 
     Dim selection As EnvDTE.TextSelection = CType(DTE.ActiveDocument.Selection(), EnvDTE.TextSelection) 
     Dim editPoint As EditPoint = selection.BottomPoint.CreateEditPoint 

     ' Get info from current line in editor 
     editPoint.StartOfLine() 
     Dim match As Match = assignmentPattern.Match(editPoint.GetText(editPoint.LineLength)) 
     If Not match.Success Then 
      MessageBox.Show("No assignment on row") 
      Exit Sub 
     End If 
     Dim foundDeclaredType As Boolean = match.Groups("DeclaredType").Success AndAlso match.Groups("DeclaredType").Value <> "var" 
     Dim foundCreatedType As Boolean = match.Groups("new").Success 

     If Not (foundDeclaredType OrElse foundCreatedType) Then 
      MessageBox.Show("Can't find type on row") 
      Exit Sub 
     End If 

     Dim typeToExpand As String = If(foundDeclaredType, match.Groups("DeclaredType"), match.Groups("CreatedType")).Value 

     ' Traverse upwards in current file and record all using statements 
     Dim currentFunction As CodeElement = FindCodeElement(selection.ActivePoint, DTE.ActiveDocument.ProjectItem.FileCodeModel.CodeElements) 
     If currentFunction Is Nothing Then 
      MessageBox.Show("Can't find current function") 
      Exit Sub 
     End If 
     mUsings.Clear() 
     FindAllUsings(currentFunction) 

     ' Loop all projects in solution to find requested type 
     Dim classType As CodeElement = DTE.Solution.Projects.Cast(Of Project) _ 
                  .Select(Function(x) FindClassInProjectItems(x.ProjectItems, typeToExpand)) _ 
                  .FirstOrDefault(Function(x) x IsNot Nothing) 
     If classType Is Nothing Then 
      MessageBox.Show("Can't find type in solution: " & typeToExpand) 
      Exit Sub 
     End If 

     PrintMemberAssignments(editPoint, match.Groups("Indent").Value & match.Groups("VariableName").Value, GetMembers(classType)) 

    Catch objException As System.Exception 
     MessageBox.Show(objException.Message) 
    End Try 
End Sub 

' Records all using statements active for a codeelement 
Sub FindAllUsings(ByVal elem As Object) 
    If TypeOf elem Is CodeFunction Then 
     FindAllUsings(CType(elem, CodeFunction).Parent) 
    ElseIf TypeOf elem Is CodeClass Then 
     mUsings.Add(CType(elem, CodeClass).FullName) 
     FindAllUsings(CType(elem, CodeClass).Parent) 
    ElseIf TypeOf elem Is CodeStruct Then 
     mUsings.Add(CType(elem, CodeStruct).FullName) 
     FindAllUsings(CType(elem, CodeStruct).Parent) 
    ElseIf TypeOf elem Is CodeNamespace Then 
     mUsings.Add(CType(elem, CodeNamespace).FullName) 
     For Each ns As String In CType(elem, CodeNamespace).Members.OfType(Of CodeImport) _ 
                    .Select(Function(x) x.Namespace) 
      mUsings.Add(ns) 
     Next 
     FindAllUsings(CType(elem, CodeNamespace).Parent) 
    ElseIf TypeOf elem Is FileCodeModel Then 
     For Each ns As String In CType(elem, FileCodeModel).CodeElements.OfType(Of CodeImport) _ 
                     .Select(Function(x) x.Namespace) 
      mUsings.Add(ns) 
     Next 
    End If 
End Sub 

' Find code element (i.e. function) for current line 
Public Function FindCodeElement(ByVal caretPosition As TextPoint, ByVal elems As CodeElements) As CodeElement 
    If elems Is Nothing Then Return Nothing 
    Return elems.Cast(Of CodeElement) _ 
       .Where(Function(x) x.StartPoint.LessThan(caretPosition) AndAlso _ 
            x.EndPoint.GreaterThan(caretPosition)) _ 
       .Select(Function(x) If(FindCodeElement(caretPosition, GetMembers(x)), x)) _ 
       .FirstOrDefault() 
End Function 


Public Sub PrintMemberAssignments(ByVal editPoint As EditPoint, ByVal prefix As String, ByVal members As CodeElements) 
    For Each member As CodeElement In members 
     Dim text As String 
     If TypeOf member Is CodeProperty Then 
      If CType(member, CodeProperty).Setter Is Nothing Then Continue For 
      If CType(member, CodeProperty).Setter.Access <> vsCMAccess.vsCMAccessPublic Then Continue For 
      If CType(member, CodeProperty).Setter.IsShared Then Continue For 
      text = MemberAssignment(prefix, member.Name, CType(member, CodeProperty).Type) 
     ElseIf TypeOf member Is CodeVariable Then 
      If CType(member, CodeVariable).Access <> vsCMAccess.vsCMAccessPublic Then Continue For 
      If CType(member, CodeVariable).IsConstant Then Continue For 
      If CType(member, CodeVariable).IsShared Then Continue For 
      text = MemberAssignment(prefix, member.Name, CType(member, CodeVariable).Type) 
     Else 
      Continue For 
     End If 
     editPoint.EndOfLine() 
     editPoint.Insert(ControlChars.NewLine) 
     editPoint.Insert(text) 
    Next 
End Sub 

Private Function MemberAssignment(ByVal prefix As String, ByVal membername As String, ByVal typeref As EnvDTE.CodeTypeRef) As String 
    Dim typekind As EnvDTE.vsCMTypeRef = typeref.TypeKind 
    Dim value As String 
    If typekind = vsCMTypeRef.vsCMTypeRefArray Then 
     value = "{0}.{1} = new {2}[1];" 
     If typeref.ElementType.TypeKind = vsCMTypeRef.vsCMTypeRefCodeType Then 
      value = value & ControlChars.NewLine & "{0}.{1}[0] = new {2}();" 
     End If 
     Return String.Format(value, prefix, membername, TrimKnownNamespace(typeref.ElementType.AsString)) 
    ElseIf typekind = vsCMTypeRef.vsCMTypeRefBool Then 
     value = "false" 
    ElseIf typekind = vsCMTypeRef.vsCMTypeRefChar Then 
     value = "'x'" 
    ElseIf typekind = vsCMTypeRef.vsCMTypeRefDecimal Then 
     value = "0.00m" 
    ElseIf typekind = vsCMTypeRef.vsCMTypeRefDouble Then 
     value = "0.00" 
    ElseIf typekind = vsCMTypeRef.vsCMTypeRefInt Then 
     value = "0" 
    ElseIf typekind = vsCMTypeRef.vsCMTypeRefLong Then 
     value = "0" 
    ElseIf typekind = vsCMTypeRef.vsCMTypeRefShort Then 
     value = "0" 
    ElseIf typekind = vsCMTypeRef.vsCMTypeRefByte Then 
     value = "0" 
    ElseIf typekind = vsCMTypeRef.vsCMTypeRefString Then 
     value = """" & membername & """" 
    ElseIf typekind = vsCMTypeRef.vsCMTypeRefArray Then 
     value = "new " & TrimKnownNamespace(typeref.ElementType.AsString) & "[1]" 
    ElseIf typekind = vsCMTypeRef.vsCMTypeRefCodeType AndAlso _ 
      typeref.AsString = "System.DateTime" Then 
     value = String.Format("new DateTime({0:yyyy},{0:%M},{0:%d})", DateTime.Today) 
    Else 
     value = "new " & TrimKnownNamespace(typeref.AsString) & "()" 
    End If 
    Return String.Format("{0}.{1} = {2};", prefix, membername, value) 
End Function 

Private Function TrimKnownNamespace(ByVal fullName As String) As String 
    Return fullName.Substring(mUsings.Where(Function(x) fullName.StartsWith(x) AndAlso _ 
                 fullName.Length > x.Length AndAlso _ 
                 fullName(x.Length) = "."c) _ 
            .Select(Function(x) x.Length + 1) _ 
            .DefaultIfEmpty(0) _ 
            .Max()) 
End Function 

Private Function FindClassInProjectItems(ByVal nprojectItems As ProjectItems, ByVal classname As String) As CodeElement 
    If nprojectItems Is Nothing Then Return Nothing 
    For Each nprojectitem As ProjectItem In nprojectItems 
     Dim found As CodeElement 
     If nprojectitem.Kind = EnvDTE.Constants.vsProjectItemKindPhysicalFile Then 
      If nprojectitem.FileCodeModel Is Nothing Then Continue For 
      found = FindClassInCodeElements(nprojectitem.FileCodeModel.CodeElements, classname) 
      If found IsNot Nothing Then Return found 
     End If 
     If nprojectitem.SubProject IsNot Nothing Then 
      found = FindClassInProjectItems(nprojectitem.SubProject.ProjectItems, classname) 
      If found IsNot Nothing Then Return found 
     End If 
     found = FindClassInProjectItems(nprojectitem.ProjectItems, classname) 
     If found IsNot Nothing Then Return found 
    Next 
End Function 

Private Function FindClassInCodeElements(ByVal elems As CodeElements, ByVal classname As String) As CodeElement 
    If elems Is Nothing Then Return Nothing 
    For Each elem As CodeElement In elems 
     If IsClassType(elem) Then 
      If classname = elem.Name Then Return elem 
     ElseIf Not TypeOf elem Is CodeNamespace Then 
      Continue For 
     End If 
     If mUsings.Contains(elem.FullName) Then 
      Dim found As CodeElement = FindClassInCodeElements(GetMembers(elem), classname) 
      If found IsNot Nothing Then Return found 
     End If 
    Next 
    Return Nothing 
End Function 

Private Function GetMembers(ByVal elem As CodeElement) As CodeElements 
    If TypeOf elem Is CodeClass Then 
     Return CType(elem, CodeClass).Members 
    ElseIf TypeOf elem Is CodeNamespace Then 
     Return CType(elem, CodeNamespace).Members 
    ElseIf TypeOf elem Is CodeStruct Then 
     Return CType(elem, CodeStruct).Members 
    ElseIf TypeOf elem Is CodeInterface Then 
     Return CType(elem, CodeInterface).Members 
    End If 
    Return Nothing 
End Function 

Private Function IsClassType(ByVal elem As CodeElement) As Boolean 
    Return TypeOf elem Is CodeClass OrElse TypeOf elem Is CodeStruct OrElse TypeOf elem Is CodeInterface 
End Function 
+0

有沒有辦法在VS2015中使用它? – user230910 2015-12-10 06:54:53

+0

@ user230910,相同的代碼在VS2015中正常工作,但您需要創建一個VS-addin來承載它。我使用了VS2012中提供的標準宏(也許VS2010)將我的宏轉換爲插件。 – adrianm 2015-12-12 07:49:14