C# 在Visual Studio加载项中-如何检索文本选择对象的属性(Visual Commander)

C# 在Visual Studio加载项中-如何检索文本选择对象的属性(Visual Commander),c#,visual-studio,visual-studio-2012,add-in,C#,Visual Studio,Visual Studio 2012,Add In,一天多来,我一直在为这件事挠头: 实际上,我正在尝试为Visual Studio 2012构建一个外接程序,该外接程序执行以下操作: 使用当前选定的变量名,查找它是其实例的类,然后在其自己的行中为每个属性键入veriable.property: 之前: 认为我被选中了 int CountPerson(Person myPerson) { *myPerson* } 之后: int CountPerson(Person myPerson) { myPerson.Name m

一天多来,我一直在为这件事挠头:

实际上,我正在尝试为Visual Studio 2012构建一个外接程序,该外接程序执行以下操作:

使用当前选定的变量名,查找它是其实例的类,然后在其自己的行中为每个属性键入veriable.property:

之前:

认为我被选中了

int CountPerson(Person myPerson)
{
    *myPerson*
}
之后:

int CountPerson(Person myPerson)
{
    myPerson.Name
    myPerson.Surname
    myPerson.Age
}
我在这里就stackoverflow提出了一个类似的问题,并得到了我现在正在寻求的答案。

以下是到目前为止的源代码:

using EnvDTE;
using EnvDTE80;
using System;
using System.ComponentModel;
using System.Collections;
using System.Collections.Generic;
using System.Collections.ObjectModel;


public class C : VisualCommanderExt.ICommand
{
    public void Run(EnvDTE80.DTE2 DTE, Microsoft.VisualStudio.Shell.Package package) 
    {
        EnvDTE.TextSelection ts = DTE.ActiveWindow.Selection as EnvDTE.TextSelection;
        if (ts == null)
            return;

        EnvDTE.CodeClass codeClass = ts.ActivePoint.CodeElement[vsCMElement.vsCMElementClass]   as     EnvDTE.CodeClass;
        if (codeClass == null)
            return;

        string properties = "";
        foreach (CodeElement elem in codeClass.Members)
        {
            if (elem.Kind == vsCMElement.vsCMElementProperty)
                properties += elem.Name + System.Environment.NewLine;
        }
        ts.Text = properties;   

    }
}
除了完全忽略选定的文本,而是打印当前类的属性之外,这种方法工作得非常好。我需要选择的变量类的属性

我将和打字的人而不是我的人生活在一起,如果这能让事情变得更容易的话

我在互联网上找到了以下链接,但无法实现逻辑:


它们可能会帮助您帮助我?

您可以在函数定义行中的函数参数名称上设置光标,并使用以下代码生成属性列表:

添加对Microsoft.VisualStudio.Shell.Design的引用

public void Run(EnvDTE80.DTE2 DTE, Microsoft.VisualStudio.Shell.Package package) 
{
    EnvDTE.TextSelection ts = DTE.ActiveWindow.Selection as EnvDTE.TextSelection;
    if (ts == null)
        return;

    EnvDTE.CodeParameter codeParam = ts.ActivePoint.CodeElement[vsCMElement.vsCMElementParameter] as EnvDTE.CodeParameter;
    if (codeParam == null)
        return;

    System.Type tClass = GetTypeByName(DTE, package, codeParam.Type.AsFullName);
    string properties = "";
    foreach (var p in tClass.GetProperties())
    {
            properties += codeParam.Name + "." + p.Name + System.Environment.NewLine;
    }
    System.Windows.Clipboard.SetText(properties);
    System.Windows.MessageBox.Show(properties);
}

private System.Type GetTypeByName(EnvDTE80.DTE2 DTE, Microsoft.VisualStudio.Shell.Package package, string name)
{
    System.IServiceProvider serviceProvider = package as System.IServiceProvider;
    Microsoft.VisualStudio.Shell.Design.DynamicTypeService typeService = 
        serviceProvider.GetService(typeof(Microsoft.VisualStudio.Shell.Design.DynamicTypeService)) as
        Microsoft.VisualStudio.Shell.Design.DynamicTypeService;

    Microsoft.VisualStudio.Shell.Interop.IVsSolution sln = 
        serviceProvider.GetService(typeof(Microsoft.VisualStudio.Shell.Interop.IVsSolution)) as
        Microsoft.VisualStudio.Shell.Interop.IVsSolution;

    Microsoft.VisualStudio.Shell.Interop.IVsHierarchy hier;
    sln.GetProjectOfUniqueName(DTE.ActiveDocument.ProjectItem.ContainingProject.UniqueName, out hier);

    return typeService.GetTypeResolutionService(hier).GetType(name, true);
}

好的,感谢上面的Sergey,我现在有了下面的代码来回答我的大部分问题:

using EnvDTE;
using EnvDTE80;
using System;

public class C : VisualCommanderExt.ICommand
{
        public void Run(EnvDTE80.DTE2 DTE, Microsoft.VisualStudio.Shell.Package package) 
        {
            EnvDTE.TextSelection ts = DTE.ActiveWindow.Selection as EnvDTE.TextSelection;
            if (ts == null)
                    throw new Exception("No Selection");

                EnvDTE.CodeParameter codeParam = ts.ActivePoint.CodeElement[vsCMElement.vsCMElementParameter] as EnvDTE.CodeParameter;
                if (codeParam == null)
                    throw new Exception("Not Parameter");

                System.Type tClass = GetTypeByName(DTE, package, codeParam.Type.AsFullName);
                string properties = System.Environment.NewLine;
                foreach (var p in tClass.GetProperties())
                {
                    properties += codeParam.Name + "." + p.Name + System.Environment.NewLine;
                }

                // Move into the method and dump the properties there
                ts.FindText("{");
                ts.Insert("{" + properties);
            }


    private System.Type GetTypeByName(EnvDTE80.DTE2 DTE, Microsoft.VisualStudio.Shell.Package package, string name)
    {
        System.IServiceProvider serviceProvider = package as System.IServiceProvider;
        Microsoft.VisualStudio.Shell.Design.DynamicTypeService typeService = 
            serviceProvider.GetService(typeof(Microsoft.VisualStudio.Shell.Design.DynamicTypeService)) as
                Microsoft.VisualStudio.Shell.Design.DynamicTypeService;

        Microsoft.VisualStudio.Shell.Interop.IVsSolution sln = serviceProvider.GetService(typeof(Microsoft.VisualStudio.Shell.Interop.IVsSolution)) as
            Microsoft.VisualStudio.Shell.Interop.IVsSolution;

        Microsoft.VisualStudio.Shell.Interop.IVsHierarchy hier;
        sln.GetProjectOfUniqueName(DTE.ActiveDocument.ProjectItem.ContainingProject.UniqueName, out hier);

        return typeService.GetTypeResolutionService(hier).GetType(name, true);
    }
}
当前问题:

    * It doesnt work for a variable in the code only for function parameters
我发现这可能会有所帮助:虽然代码超出了我的技能范围

哇,这太棒了,非常接近我要找的东西。唯一的区别是光标的位置和输出位置。为什么它必须在函数行上?好的,我设法将结果输入到方法中:ts.LineDown;ts.LineDown;星线;插入属性;因此,剩下的唯一问题是使用代码中选择的变量,而不是强制用户选择函数parameter@user230910:两行向下移动到功能体?如果打开了怎么办{是否与方法签名在同一行?@user230910 Visual Studio代码模型不支持局部变量,这就是我使用函数声明的原因。也许可以使用其他命令代码从所选变量名转到函数参数。您是否成功创建了扩展名?是否已将其放到Visua上l Studio gallery还没有?下面的代码是我所能得到的,我最终放弃了,没有了它就生活了如果你介意帮我做更多的话?我自己做了一个Visual Studio的扩展,在那里我得到了当前选择所在的类名和方法名。我在GitHub上有源代码,它叫浏览,可能是我可以帮你吗?谢谢,我会帮你的