使用评估后的MSBuild属性值编程强制更新Visual Studio Intellisense

3
我正在尝试创建一个VSIX扩展,将下拉菜单添加到Visual Studio工具栏,以控制自定义MSBuild属性的值。 该值确定在项目中包含哪个版本的COMReference,并且必须在不覆盖.csproj文件的情况下设置。下面是我的.csproj文件的一部分:
<Project ... >
<Choose>
    <When Condition="'$(MyProperty)'=='MyValue1'">
      <ItemGroup>
        <COMReference Include="ComLib">
          Version_1
        </COMReference>
      </ItemGroup>
    </When>
    <When Condition="'$(MyProperty)'=='MyValue2'">
      <ItemGroup>
        <COMReference Include="ComLib">
          Version_2
        </COMReference>
      </ItemGroup>
    </When>
  </Choose>
</Project>

I found 2 possible solutions:

First

public static void SetGlobalBuildProperty( string property, string value )
{
    var projects = Microsoft.Build.Evaluation.ProjectCollection
                .GlobalProjectCollection
                .LoadedProjects;

    foreach ( Microsoft.Build.Evaluation.Project project in projects )
    {   
        project.SetGlobalProperty( property, value );
        project.MarkDirty();
        project.ReevaluateIfNecessary();    
    }
}

Broject的实际值正确构建,但Intellisense无法识别COMReferences中的任何内容,因此Intellisense功能无法正常工作,所有内容都会被标记为红色。

第二:

将属性放置在单独的文件中,并将其包含在主csproj文件中。之后通过VSIX修改.props文件。

.csproj:

...
<Include Project="generated\MyProps.props"/>
<Coose> ... </Choose>
...

MyProps:

<Project ...>
  <PropertyGroup>
    <MyProperty Condition="'$(MyProperty )' == ''">MyValue1</MyProperty>
    <DefineConstants>$(DefineConstants);$(MyProperty)</DefineConstants>
  </PropertyGroup>
</Project>

这个解决方案工作得非常糟糕。当我更改MyValue1时,重新加载“Solution Explorer”并不足够。有时即使重新启动Visual Studio也不够,您需要删除.suo文件。

如何让Intellisense更新项目信息,或者也许有人知道此问题的另一个解决方案?

1个回答

3

我找到了解决方案。 这个函数可以更新项目和智能感知:

 VSLangProj80.VSProject2.Refresh();

完整功能(刷新解决方案中的所有项目):

public static void SetGlobalBuildProperty( IServiceProvider package, string property, string value )
    {
        var projects = Microsoft.Build.Evaluation.ProjectCollection
            .GlobalProjectCollection
            .LoadedProjects;

        foreach ( var project in projects )
        {
            project.SetGlobalProperty( property, value );
            project.MarkDirty();
            project.ReevaluateIfNecessary();                    
        }
        var dte = package.GetService( typeof( DTE ) ) as DTE2;
        var solution = dte.Solution as Solution2;
        var dteProjects = GetSolutionProjects( solution ) //Get all solution projects.
        foreach( var project in dteProjects )
        {
            var vsProject = project.Object as VSProject2;
            vsproject.Refresh();
        }           
    }

我尝试了这个,调用Refresh会抛出“NotImplementedException”异常。堆栈跟踪:在VSLangProj80.VSProject2.Refresh()。你有任何想法为什么会发生这种情况吗? - GregorMohorko
很遗憾,我无法确定。可能是DTE提供程序实现的,而不是VisualStudio(例如,对于没有参数hostspecific的T4模板)。 - R. Savelyev
@GregorMogorko:也许您尝试刷新的项目不是VB或C#。文档位于:https://learn.microsoft.com/en-us/dotnet/api/vslangproj80.vsproject2?view=visualstudiosdk-2017,其中指出`VSProject2接口`*包含特定于Visual Basic或Visual C#项目的信息。当项目为Visual Basic或Visual C#项目时,Object对象将返回它。* - Pavel Stepanek

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接