在设计时,是否有一种方法可以在VisualStudio2010中初始化具有所有属性的对象

本文关键字:初始化 VisualStudio2010 对象 属性 一种 是否 方法 | 更新日期: 2023-09-27 18:21:57

背景

我正在用VS2010、.NET4、C#编写代码。此外,如果重要的话,我正在使用最新版本的ReSharper。

问题

假设我有这个型号:

public class SomeObject
        {
            public string Red{ get; set; }
            public string Green{ get; set; }
            public string Blue{ get; set; }
            public string Yellow{ get; set; }
            public string Purple{ get; set; }
            public string Orange{ get; set; }
            public string Black{ get; set; }
        }

在代码的其他地方,我需要实例化其中一个对象,如下所示:

SomeObject myObject = new SomeObject{
                                     red = "some value", 
                                     blue = "some other value",
                                     . . .,
                                     black="last value"
                                    };

*注意:*有时我只想用它的全部可能属性的子集(即,只有红色和蓝色)来初始化这个对象。

目前,我必须为SomeObject的每个新实例键入每个属性(红色、蓝色、绿色等)。VS2010中有没有热键或其他东西可以预先填充这些属性,这样我只需要为每个属性分配值,而不是键入每个值?

在设计时,是否有一种方法可以在VisualStudio2010中初始化具有所有属性的对象

您可以使用智能代码完成。

写入:新SomeObject{

然后按Ctrl+Alt+Space:->所有可能的属性都列在工具提示窗口中

然后选择一个属性(即"红色")并按ENTER键->新SomeObject{Red=}

然后键入",",再按Ctrl+Alt+Space,选择下一个属性,依此类推。

目前,我必须为SomeObject的每个新实例键入每个属性(红色、蓝色、绿色等)。

就我个人而言,如果你需要为每个对象实例设置这些参数,我会通过添加一个接受所有参数的构造函数来处理这个问题,而不使用对象初始化语法。这将为您提供充分的智能感知,但也有助于/迫使您每次都正确地构建对象

请记住,类型的构造函数应该强制您提供将对象正确初始化为正确状态所需的所有参数。对象初始化器的一个缺点是,它们在编译时不会强制执行此操作。因此,如果每个对象实例都需要所有这些属性,则构造函数应该提供它们,而不是使用对象初始化器。

所有属性总是相同的吗?为什么不在已经设置了构造函数的地方添加构造函数呢?或者不止一个。

看看代码段。我想这会给你想要的。

没有键盘快捷键来一般地准备对象初始值设定项。

VS IDE或Reshaper无法对您想要将属性设置为的值进行合理的猜测,因此必须插入无效的或充其量是次优的代码。

正如其他答案所建议的那样,你可以实施一个特定的解决方案,如果你发现自己这样做很快,那么建设者很可能是你的选择,但我不认为这是你的问题。

您真的想读/写颜色吗?如果没有,这是最简单的解决方案:

public class SomeObject
{ 
    public const string Red = "red";
    public const string Green = "green";
    public const string Blue = "blue";
    ...
}

但是,如果您希望更加灵活,并且只能初始化某些属性,则可以使用对象初始化语法。使用您原来的SomeObject实现,您可以使用创建一个新对象

var obj = new SomeObject { Red = "red", Blue = "blue" };

我创建了一个VS宏来执行此操作。我的主要用途是为我的DTO生成伪测试数据。

你写了这样一行:

var x = new SomeType();

然后,宏将为每个可写属性/成员(如)生成一行

x.IntProperty = 0;
x.StringProperty = "StringProperty";
x.DateProperty = new DateTime(2012, 1, 31);
x.SomeIntList = new List<int>();
x.SomeTypeProperty = new SomeType();

(当然,您可以在最后一行重新运行宏以生成x.SomeTypeProperty.Y = 0等)

Option Explicit On
Option Strict On
Imports System
Imports EnvDTE
Imports EnvDTE80
Imports System.Collections.Generic
Imports System.Linq
Imports System.Text.RegularExpressions
Imports System.Windows.Forms
Friend Module InitializeAllMembers
    Public DTE As EnvDTE80.DTE2
    Private ReadOnly _usings As New HashSet(Of String)
    Sub InitializeAllMembers(ByVal getValue As Boolean)
        Try
            Dim memberAssignment As Func(Of String, String, String, EnvDTE.CodeTypeRef, String) = Nothing
            Dim selection As EnvDTE.TextSelection = CType(DTE.ActiveDocument.Selection(), EnvDTE.TextSelection)
            Dim editPoint As EditPoint = selection.BottomPoint.CreateEditPoint
            editPoint.StartOfLine()
            Dim className As String = ""
            Dim indent As String = ""
            Dim variable As String = ""
            Dim parseError As String
            If DTE.ActiveDocument.ProjectItem Is Nothing Then
                MessageBox.Show("File does not belong to a project")
            End If
            If DTE.ActiveDocument.Language = "Basic" Then
                parseError = GetVbInitialization(editPoint.GetText(editPoint.LineLength), className, indent, variable)
                If getValue Then
                    memberAssignment = AddressOf VbMemberGetValue
                Else
                    memberAssignment = AddressOf VbMemberAssignment
                End If
            ElseIf DTE.ActiveDocument.Language = "CSharp" Then
                parseError = GetCSharpInitialization(editPoint.GetText(editPoint.LineLength), className, indent, variable)
                If getValue Then
                    memberAssignment = AddressOf CSharpMemberGetValue
                Else
                    memberAssignment = AddressOf CSharpMemberAssignment
                End If
            Else
                parseError = "Not supported language " & DTE.ActiveDocument.Language
            End If
            If parseError IsNot Nothing Then
                MessageBox.Show(parseError)
                Exit Sub
            End If
            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
            _usings.Clear()
            FindAllUsings(currentFunction)
            Dim classType As CodeElement = DTE.Solution.Projects.Cast(Of Project) _
                                                                .Select(Function(x) FindClassInProjectItems(x.ProjectItems, className)) _
                                                                .FirstOrDefault(Function(x) x IsNot Nothing)
            If classType Is Nothing Then
                MessageBox.Show("Can't find type in solution: " & className)
                Exit Sub
            End If
            DTE.UndoContext.Open("InitializeAllMembers")
            PrintMemberAssignments(memberAssignment, editPoint, indent, variable, GetMembers(classType))
            If TypeOf classType Is CodeClass Then
                For Each base As CodeElement In CType(classType, CodeClass).Bases
                    If TypeOf base Is CodeClass Then
                        PrintMemberAssignments(memberAssignment, editPoint, indent, variable, GetMembers(base))
                    End If
                Next
            End If
            DTE.UndoContext.Close()
        Catch objException As System.Exception
            MessageBox.Show(objException.Message)
        End Try
    End Sub
    Private Function GetVbInitialization(ByVal line As String, _
                                         ByRef className As String, _
                                         ByRef indent As String, _
                                         ByRef variable As String) As String
        Dim vbinitialization As New Regex("(?<Indent>'s*)Dim's+(?<VariableName>['S=]+)'s+(?:As's+(?:New's+)?(?<DeclaredType>[^'s'(]+))?(?:'s*='s*New's+(?<CreatedType>[^'s'(]+))?", _
                                          RegexOptions.IgnoreCase)
        Dim match As Match = vbinitialization.Match(line)
        If Not match.Success Then
            Return "No assignment on row"
        End If
        Dim foundDeclaredType As Boolean = match.Groups("DeclaredType").Success
        Dim foundCreatedType As Boolean = match.Groups("CreatedType").Success
        If Not (foundDeclaredType OrElse foundCreatedType) Then
            Return "Can't find type on row"
        End If
        className = If(foundDeclaredType, match.Groups("DeclaredType"), match.Groups("CreatedType")).Value
        indent = match.Groups("Indent").Value
        variable = match.Groups("VariableName").Value
        Return Nothing
    End Function
    Private Function GetCSharpInitialization(ByVal line As String, _
                                             ByRef className As String, _
                                             ByRef indent As String, _
                                             ByRef variable As String) As String
        Dim csharpinitialization As New Regex("(?<Indent>'s*)(?:(?<DeclaredType>'S+)'s+)?(?<VariableName>['S=]+)'s*='s*(?<new>new)?'s*(?<CreatedType>[^'s'(]+)")
        Dim match As Match = csharpinitialization.Match(line)
        If Not match.Success Then
            Return "No assignment on row"
        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
            Return "Can't find type on row"
        End If
        className = If(foundDeclaredType, match.Groups("DeclaredType"), match.Groups("CreatedType")).Value
        indent = match.Groups("Indent").Value
        variable = match.Groups("VariableName").Value
        Return Nothing
    End Function
    Sub FindAllUsings(ByVal elem As Object)
        If TypeOf elem Is CodeFunction Then
            FindAllUsings(CType(elem, CodeFunction).Parent)
        ElseIf TypeOf elem Is CodeClass Then
            _usings.Add(CType(elem, CodeClass).FullName)
            FindAllUsings(CType(elem, CodeClass).Parent)
        ElseIf TypeOf elem Is CodeStruct Then
            _usings.Add(CType(elem, CodeStruct).FullName)
            FindAllUsings(CType(elem, CodeStruct).Parent)
        ElseIf TypeOf elem Is CodeNamespace Then
            _usings.Add(CType(elem, CodeNamespace).FullName)
            For Each ns As String In CType(elem, CodeNamespace).Members.OfType(Of CodeImport) _
                                                                       .Select(Function(x) x.Namespace)
                _usings.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)
                _usings.Add(ns)
            Next
        End If
    End Sub
    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 memberAssignment As Func(Of String, String, String, CodeTypeRef, String), _
                                      ByVal editPoint As EditPoint, _
                                      ByVal indent As String, _
                                      ByVal variable As String, _
                                      ByVal members As CodeElements)
        For Each member As CodeElement In members
            Dim typeref As EnvDTE.CodeTypeRef
            If TypeOf member Is CodeProperty2 Then
                Dim prop As CodeProperty2 = CType(member, CodeProperty2)
                If prop.Setter Is Nothing Then
                    If prop.Access <> vsCMAccess.vsCMAccessPublic Then Continue For
                    If prop.ReadWrite = vsCMPropertyKind.vsCMPropertyKindReadOnly Then Continue For
                    If prop.IsShared Then Continue For
                ElseIf prop.Setter.Access <> vsCMAccess.vsCMAccessPublic Then
                    Continue For
                ElseIf prop.Setter.IsShared Then
                    Continue For
                End If
                typeref = prop.Type
            ElseIf TypeOf member Is CodeVariable Then
                Dim var As CodeVariable = CType(member, CodeVariable)
                If var.Access <> vsCMAccess.vsCMAccessPublic Then Continue For
                If var.IsConstant Then Continue For
                If var.IsShared Then Continue For
                typeref = var.Type
            Else
                Continue For
            End If
            editPoint.EndOfLine()
            editPoint.Insert(ControlChars.NewLine)
            editPoint.Insert(memberAssignment(indent, variable, member.Name, typeref))
        Next
    End Sub
    Private Function TrimKnownNamespace(ByVal fullName As String) As String
        Return fullName.Substring(_usings.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
        Return Nothing
    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 _usings.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
    Private Function CSharpMemberAssignment(ByVal indent As String, _
                                            ByVal variable 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}.{2} = new {3}[1];"
            Return String.Format(value, indent, variable, membername, TrimKnownNamespace(typeref.ElementType.AsString)) & _
                   ControlChars.NewLine & _
                   CSharpMemberAssignment(indent, variable, membername & "[0]", typeref.ElementType)
        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.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} = {3};", indent, variable, membername, value)
    End Function
    Private Function CSharpMemberGetValue(ByVal indent As String, _
                                          ByVal variable 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}.{2} = new {3}[1];"
            Return String.Format(value, indent, variable, membername, TrimKnownNamespace(typeref.ElementType.AsString)) & _
                   ControlChars.NewLine & _
                   CSharpMemberGetValue(indent, variable, membername & "[0]", typeref.ElementType)
        ElseIf typekind = vsCMTypeRef.vsCMTypeRefBool Then
            value = "src.GetBoolean()"
        ElseIf typekind = vsCMTypeRef.vsCMTypeRefChar Then
            value = "src.GetChar()"
        ElseIf typekind = vsCMTypeRef.vsCMTypeRefDecimal Then
            value = "src.GetDecimal()"
        ElseIf typekind = vsCMTypeRef.vsCMTypeRefDouble Then
            value = "src.GetDouble()"
        ElseIf typekind = vsCMTypeRef.vsCMTypeRefInt Then
            value = "src.GetInt32()"
        ElseIf typekind = vsCMTypeRef.vsCMTypeRefLong Then
            value = "src.GetInt64()"
        ElseIf typekind = vsCMTypeRef.vsCMTypeRefShort Then
            value = "src.GetInt16()"
        ElseIf typekind = vsCMTypeRef.vsCMTypeRefByte Then
            value = "src.GetByte()"
        ElseIf typekind = vsCMTypeRef.vsCMTypeRefString Then
            value = "src.GetString()"
        ElseIf typekind = vsCMTypeRef.vsCMTypeRefCodeType AndAlso _
                typeref.AsString = "System.DateTime" Then
            value = "src.GetDateTime()"
        Else
            value = "new " & TrimKnownNamespace(typeref.AsString) & "()"
        End If
        Return String.Format("{0}{1}.{2} = {3};", indent, variable, membername, value)
    End Function
    Private Function VbMemberAssignment(ByVal indent As String, _
                                        ByVal variable 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}Redim {1}.{2}(1)" ' Vb don't need type argument
            Return String.Format(value, indent, variable, membername, TrimKnownNamespace(typeref.ElementType.AsString)) & _
                   ControlChars.NewLine & _
                   VbMemberAssignment(indent, variable, membername & "(0)", typeref.ElementType)
        ElseIf typekind = vsCMTypeRef.vsCMTypeRefBool Then
            value = "False"
        ElseIf typekind = vsCMTypeRef.vsCMTypeRefChar Then
            value = """x""c"
        ElseIf typekind = vsCMTypeRef.vsCMTypeRefDecimal Then
            value = "0.00d"
        ElseIf typekind = vsCMTypeRef.vsCMTypeRefDouble Then
            value = "0.00r"
        ElseIf typekind = vsCMTypeRef.vsCMTypeRefInt Then
            value = "0"
        ElseIf typekind = vsCMTypeRef.vsCMTypeRefLong Then
            value = "0L"
        ElseIf typekind = vsCMTypeRef.vsCMTypeRefShort Then
            value = "0s"
        ElseIf typekind = vsCMTypeRef.vsCMTypeRefByte Then
            value = "0 AS Byte"
        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 = "Date" Then
            value = String.Format("new Date({0:yyyy}, {0:%M}, {0:%d})", DateTime.Today)
        Else
            value = "new " & TrimKnownNamespace(typeref.AsString) & "()"
        End If
        Return String.Format("{0}{1}.{2} = {3}", indent, variable, membername, value)
    End Function
    Private Function VbMemberGetValue(ByVal indent As String, _
                                        ByVal variable 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}Redim {1}.{2}(1)" ' Vb don't need type argument
            Return String.Format(value, indent, variable, membername, TrimKnownNamespace(typeref.ElementType.AsString)) & _
                   ControlChars.NewLine & _
                   VbMemberGetValue(indent, variable, membername & "(0)", typeref.ElementType)
        ElseIf typekind = vsCMTypeRef.vsCMTypeRefBool Then
            value = "src.GetBoolean()"
        ElseIf typekind = vsCMTypeRef.vsCMTypeRefChar Then
            value = "src.GetChar()"
        ElseIf typekind = vsCMTypeRef.vsCMTypeRefDecimal Then
            value = "src.GetDecimal()"
        ElseIf typekind = vsCMTypeRef.vsCMTypeRefDouble Then
            value = "src.GetDouble()"
        ElseIf typekind = vsCMTypeRef.vsCMTypeRefInt Then
            value = "src.GetInt32()"
        ElseIf typekind = vsCMTypeRef.vsCMTypeRefLong Then
            value = "src.GetInt64()"
        ElseIf typekind = vsCMTypeRef.vsCMTypeRefShort Then
            value = "src.GetInt16()"
        ElseIf typekind = vsCMTypeRef.vsCMTypeRefByte Then
            value = "src.GetByte()"
        ElseIf typekind = vsCMTypeRef.vsCMTypeRefString Then
            value = "src.GetString()"
        ElseIf typekind = vsCMTypeRef.vsCMTypeRefArray Then
            value = "New " & TrimKnownNamespace(typeref.ElementType.AsString) & "(1)"
        ElseIf typekind = vsCMTypeRef.vsCMTypeRefCodeType AndAlso _
                typeref.AsString = "Date" Then
            value = "src.GetDateTime()"
        Else
            value = "new " & TrimKnownNamespace(typeref.AsString) & "()"
        End If
        Return String.Format("{0}{1}.{2} = {3}", indent, variable, membername, value)
    End Function
End Module

早上好,您应该可以通过创建Visual Studio代码段来完成这项工作或者通过创建ReSharper代码模板