问题
I have scratched my head for over a day on this:
Essentially I am attempting to build an Add-In for Visual Studio 2012 that does the following:
Take the variable name that is currently selected, go and find the class that it is an instance of, then type the veriable.property for each property on its own line:
BEFORE:
eg. (Consider myPerson is selected)
int CountPerson(Person myPerson)
{
*myPerson*
}
AFTER:
int CountPerson(Person myPerson)
{
myPerson.Name
myPerson.Surname
myPerson.Age
}
I have asked a similar question here on stackoverflow, and received the answer that I am now pursuing. Visual Studio dump all properties of class into editor
Here is the source code so far:
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;
}
}
This works perfectly fine, except that it completely ignores the selected text, and instead prints the properties of the current class. I need the properties of the class of the variable I am selecting.
I will live with typing "Person" instead of |myPerson" if that will make things easier.
I have found the following links on the internet, but was unable to implement the logic: http://blogs.clariusconsulting.net/kzu/how-to-get-a-system-type-from-an-envdte-codetyperef-or-envdte-codeclass/ http://www.visualstudioextensibility.com/2008/03/06/how-do-i-get-a-system-type-from-a-type-name/
They may help you with helping me?
回答1:
You can set the cursor on a function parameter name in the function definition line and generate properties list with the following code:
(add a reference to 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);
}
回答2:
Ok, thanks to Sergey above I now have the below code that answers most of my question:
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);
}
}
Current Issues:
* It doesnt work for a variable in the code only for function parameters
I found this which might help: (The code is waaaay beyond my skills though) Auto generate properties when creating object
来源:https://stackoverflow.com/questions/25724189/in-visual-studio-add-in-how-can-i-retrieve-the-properties-of-the-text-selectio