【问题标题】:Auto generate properties when creating object创建对象时自动生成属性
【发布时间】:2011-06-10 07:45:46
【问题描述】:

我的类有很多属性,我想知道当我创建对象时,Visual Studio、Resharper 或其他工具有什么方法可以创建调用属性的语法。所以我不必自己检查所有属性,只需设置值即可。像这样的东西。

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

我不知道人们是否理解这个问题。我希望 Visual Studio 在创建对象时为属性创建设置器。不是财产本身。

【问题讨论】:

  • 即使是一个小工具来自动创建一个带有所有参数的构造函数也会很棒。一些 O/R 映射器实际上创建了一个构造器,采用所有参数来填充所有属性,以获取可能有帮助的简单对象。

标签: c# .net visual-studio resharper


【解决方案1】:

您可以在构造函数中使用命名参数:

http://geekswithblogs.net/michelotti/archive/2009/01/22/c-4.0-named-parameters-for-better-code-quality.aspx

例如:

Person person = new Person(firstName: "John", lastName: "Smith", dateOfBirth: new DateTime(1970, 1, 1));

【讨论】:

    【解决方案2】:

    编辑 误解了问题

    我有一个来自这一行的宏

    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
    

    【讨论】:

    • 有没有办法在 VS2015 中使用这个?
    • @user230910,相同的代码在 VS2015 中运行良好,但您需要创建一个 VS-addin 来托管它。我使用了 VS2012(也可能是 VS2010)中提供的标准宏将我的宏转换为插件。
    【解决方案3】:

    您可以使用匿名对象:

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

    在这种情况下,将创建具有属性onetwothree 的新对象

    【讨论】:

      【解决方案4】:

      Intellisense 不是为您做最多的工作吗?通常,只要您打开 { an press space,它就会向您显示所有属性的列表。

      【讨论】:

      • 是的,但是当它们有很多时,你会自动想要它们;)。
      • 同意@TuomasK 并希望这里有一些好的解决方案。也许我需要企业许可证?还是重新锐化?
      猜你喜欢
      • 1970-01-01
      • 2014-03-19
      • 1970-01-01
      • 1970-01-01
      • 2015-12-22
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多