- r - 以节省内存的方式增长 data.frame
- ruby-on-rails - ruby/ruby on rails 内存泄漏检测
- android - 无法解析导入android.support.v7.app
- UNIX 域套接字与共享内存(映射文件)
我编写了如下代码:
[Attrib(typeof(MyCustomType))]
public class TargetType
{
// .....
}
我想使用 EnvDTE
获取对 typeof
引用的 CodeElement
的引用。我知道如何获取对属性参数的引用,并且我可以使用 Value
,但这给了我字符串 typeof(MyCustomType)
。
如果我使用 Value
,我必须分解字符串然后尝试找到类型,如果有两个名称相同但命名空间不同的类型,这会变得很麻烦。
有更简单的方法吗?
最佳答案
Is there an easier way to do this?
不,我不这么认为,至少对于 <= VS2013,CodeAttributeArgument
似乎没有更进一步,这很遗憾。他们应该发布 CodeAttributeArgument2
,它的 Value
为 CodeExpr
:\..
如果您使用 >=VS2014,您可以访问 Roslyn,并且它应该 变得更容易 - 不知道如何在 VS 扩展中访问 roslyn ,还得拭目以待。
为了获取属性,您可以使用 VS 助手:
public List<CodeElement> GetAllCodeElementsOfType(
CodeElements elements,
vsCMElement elementType,
bool includeExternalTypes)
{
var ret = new List<CodeElement>();
foreach (CodeElement elem in elements)
{
// iterate all namespaces (even if they are external)
// > they might contain project code
if (elem.Kind == vsCMElement.vsCMElementNamespace)
{
ret.AddRange(
GetAllCodeElementsOfType(
((CodeNamespace)elem).Members,
elementType,
includeExternalTypes));
}
// if its not a namespace but external
// > ignore it
else if (elem.InfoLocation == vsCMInfoLocation.vsCMInfoLocationExternal && !includeExternalTypes)
continue;
// if its from the project
// > check its members
else if (elem.IsCodeType)
{
ret.AddRange(
GetAllCodeElementsOfType(
((CodeType)elem).Members,
elementType,
includeExternalTypes));
}
if (elem.Kind == elementType)
ret.Add(elem);
}
return ret;
}
与此同时,您可以使用回溯解决方案,这不是很好,但它应该可以工作,还没有完全 100% 地测试它。基本思想是从类开始向后跟踪,并跟踪类路径中的不同命名空间/使用。如果要解析类型,这将尝试模拟真正的编译器几乎会做什么:
var solution = (Solution2) _applicationObject.Solution;
var projects = solution.Projects;
var activeProject = projects
.OfType<Project>()
.First();
// locate my class.
var myClass = GetAllCodeElementsOfType(
activeProject.CodeModel.CodeElements,
vsCMElement.vsCMElementClass, false)
.OfType<CodeClass2>()
.First(x => x.Name == "Program");
// locate my attribute on class.
var mySpecialAttrib = myClass
.Attributes
.OfType<CodeAttribute2>()
.First();
var attributeArgument = mySpecialAttrib.Arguments
.OfType<CodeAttributeArgument>()
.First();
string myType = Regex.Replace(
attributeArgument.Value, // typeof(MyType)
"^typeof.*\\((.*)\\)$", "$1"); // MyType*/
var codeNamespace = myClass.Namespace;
var classNamespaces = new List<string>();
while (codeNamespace != null)
{
var codeNs = codeNamespace;
var namespaceName = codeNs.FullName;
var foundNamespaces = new List<string> {namespaceName};
// generate namespaces from usings.
var @usings = codeNs.Children
.OfType<CodeImport>()
.Select(x =>
new[]
{
x.Namespace,
namespaceName + "." + x.Namespace
})
.SelectMany(x => x)
.ToList();
foundNamespaces.AddRange(@usings);
// prepend all namespaces:
var extra = (
from ns2 in classNamespaces
from ns1 in @usings
select ns1 + "." + ns2)
.ToList();
classNamespaces.AddRange(foundNamespaces);
classNamespaces.AddRange(extra);
codeNamespace = codeNs.Parent as CodeNamespace;
if (codeNamespace == null)
{
var codeModel = codeNs.Parent as FileCodeModel2;
if (codeModel == null) return;
var elems = codeModel.CodeElements;
if (elems == null) continue;
var @extraUsings = elems
.OfType<CodeImport>()
.Select(x => x.Namespace);
classNamespaces.AddRange(@extraUsings);
}
}
// resolve to a type!
var typeLocator = new EnvDTETypeLocator();
var resolvedType = classNamespaces.Select(type =>
typeLocator.FindTypeExactMatch(activeProject, type + "." + myType))
.FirstOrDefault(type => type != null);
你需要EnvDTETypeLocator也是。
对于 VS2015,可以从此处找到 roslyn 集成的示例:https://github.com/tomasr/roslyn-colorizer/blob/master/RoslynColorizer/RoslynColorizer.cs
它肯定会比使用当前的 CodeModel
容易得多。
关于c# - 从 DTE 访问属性信息,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/9520802/
在我的包中,我使用 (DTE) GetService(typeof (DTE)) 获取有关当前打开的解决方案的信息。有没有一种方法可以模拟这个以进行测试,特别是这样我就可以使用 dte.Solutio
我正在尝试在Powershell中做一些非常简单的事情,我有一个ProjectItem实例,我想读取FileNames属性的值(记录为字符串数组)。但是事实证明这是相当困难的 ForEach ($it
我想使用宏来发布我的网络应用程序项目。小问题是,DTE.ExecuteCommand 异步运行,我需要等到命令完成。 例子: DTE.Windows.Item(Constants.vsWind
我编写了如下代码: [Attrib(typeof(MyCustomType))] public class TargetType { // ..... } 我想使用 EnvDTE 获取对 type
我正在尝试使用 PowerShell 来自动化创建基于种子(例如 EDMX 文件或 DbContext)配置的 n 层解决方案的过程。我希望能够打开一个框架解决方案,获取事件实例,并使用自动生成的代码
我的 Visual Studio 程序包需要使用 EnvDTE.DTE 变量,但返回时始终为空。在阅读了许多 hack 之后,他们都说使用 OnShellPropertyChange() 方法 (IV
我正在编写 Visual Studio 2008 扩展。我想在每次 DTE.ActiveDocument 更改时收到通知,因此我可以在自定义面板中更新某些内容,该面板执行与解决方案资源管理器类似的功能
我一直在慢慢研究 Visual Studio 的 SDK,但还不能弄清楚 DTE 代表什么。这是一个愚蠢的问题,但我似乎真的找不到它。 DTE 非常有用,如果知道它是什么,那就太酷了。 最佳答案 它代
我正在尝试自动将焦点从解决方案资源管理器中的一个 .ProjectItem 更改为另一个 .ProjectItem。我想以编程方式将焦点从一个项目更改到另一个项目,但似乎不知道如何操作。 这是我到目前
使用VS2010 感谢汉斯(因为我要低调地回答我自己的问题8个小时) Sub CreateBreakPoint() Dim doc As TextDocument = _
我正在尝试在浏览器 JavaScript 中捕获 Visual Studio 扩展事件,DTE 可通过 window.external 获得: window.external.DTE.Events.S
在这段代码中,在我尝试为 Vs2010 编写的插件中 _applicationObject.ItemOperations.NewFile( "General\\Text File", File
是否可以通过DTE mDte变量获取visual studio实例的进程id?引用下面的代码。 private static DTE mDte; public static void
如何获取所有正在运行的 Visual Studio 实例以便我可以执行自动化? (添加此问题是因为 this one 已关闭) 最佳答案 使用运行对象表获取所有实例,然后选择你想要的。 我认为没有比这
我为我的 VSPackage 创建了一个自定义输出窗口 Pane : 使用此代码: // Creating Output Window for our package. IVsOutputWindow
我正在使用 DTE 来跟踪何时从解决方案中加载和删除项目,以便我可以更新自定义测试资源管理器扩展。然后我触发容器发现过程。但是,当解决方案首次加载时,它会异步加载一些项目并触发大量项目添加事件。 我真
我正在尝试为 vs2010 编写我的第一个插件,但我很挣扎。 我有一个生成大量 cs 文件的程序集。我希望我的插件将新文件添加到所选项目,或者如果文件存在,则覆盖它们。 我有两个问题: 添加新文件时,
我有一个设计师依赖于其他解决方案的存在。如果其中一项被删除,设计器就会崩溃,您必须以 XML 格式进行编辑才能修复。不完全是用户友好的。 但是,我确实拥有代表 Visual Studio 实例的 DT
我有一个仅用于命令行的 C++ VSPackage。在我的 pkgdef 文件中设置以下 Autoload 注册表项,不会在从命令行运行 devenv 时强制加载 VSPackage。 [$RootK
我正在尝试在 Visual Studio 2012 中自动化程序包管理器控制台窗口。我是 DTE 对象以实现相同的目的。通过使用下面的代码行,我可以打开包管理器控制台窗口。 DTE.ExecuteCo
我是一名优秀的程序员,十分优秀!