Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Access AllEvaluatedItems (not just ordered with respect to items of the same item type) from within .csproj #4460

Open
aodl opened this issue Jun 21, 2019 · 4 comments
Labels
Milestone

Comments

@aodl
Copy link

aodl commented Jun 21, 2019

Feature Enquiry

Is it possible from inside a .csproj file (perhaps using a custom MSBuild task) to access an ordered list of project items that are not just ordered with respect to the same item type? So, in the example below, being able to determine that one dog comes before the cat and another one comes after it.

<ItemGroup>
    <dog Include="bark" />
    <cat Include="meow" />
    <dog Include="woof" />
</ItemGroup>

<!--
@(dog) is only ordered with respect to other dogs :(
!-->

I'm aware that this property appears to provide this behaviour, but I only know how to access this from a VS extension project, not from inside MSBuild. Is this possible?

@rainersigwald
Copy link
Member

No, that's not possible.

As a rule, MSBuild doesn't make it possible to observe project state from inside a project; rather it requires explicit reference to the items or properties you are referencing. This makes it easier to reason about what a given snippet of code will do.

May I ask what you're doing that led you to ask about this?

@aodl
Copy link
Author

aodl commented Jun 21, 2019

That's a shame. It would be nice if MSBuild exposed a way to enumerate all project items in the order that they are declared (irrespective of item type).

What I would like to be able to do is declare some ProjectReferences before some PackageReferences and vice versa in a project file, like below ↓, and then be able to determine the exact ordering at build time in a task:

<ItemGroup>
   <PackageReference Include="somePackage">
   <ProjectReference Include="someProject">
   <PackageReference Include="someOtherPackage">
   <ProjectReference Include="someOtherProject">
</ItemGroup>

<!--  or even...  -->

<ItemGroup>
   <PackageReference Include="somePackage">
</ItemGroup>
<ItemGroup>
   <ProjectReference Include="someProject">
</ItemGroup>
<ItemGroup>
   <PackageReference Include="someOtherPackage">
</ItemGroup>
<ItemGroup>
   <ProjectReference Include="someOtherProject">
</ItemGroup>

<!-- and then... -->

<Task Name="WriteOrderedRefsToFile" BeforeTargets="BeforeBuild">
<!-- write the ordered references to a file for lookup at runtime -->
</Task>

Essentially I would like the order that a project's dependencies are declared in to be meaningful (regardless of whether they are project or package references), and at runtime I can use this order to affect the execution order of 'jobs' exposed by those dependencies.

Can you think of a way to achieve this? At the moment I'm stuck doing something like this (unless of course I want to depend on a custom VS extension).

<ItemGroup>
  <ProjectReference Include="someProject" RefOrder="1">
  <PackageReference Include="someProject" RefOrder="2">
  <ProjectReference Include="someProject" RefOrder="3">
</ItemGroup>

↑ this approach isn't very convenient/maintainable as new references are added or when reordering is required :(

@livarcocc
Copy link
Contributor

And why do you need to implement such approach? What are you trying to achieve with that. I believe the manual approach is the only thing that I can think of. Though, in my opinion, neither of them would be particularly maintainable.

@livarcocc livarcocc added this to the Discussion milestone Jun 25, 2019
@aodl
Copy link
Author

aodl commented Jun 26, 2019

There are three reasons I can think of;

  • Why order matters: The dependencies in question each encapsulate a handler that's responsible for participating in a chain of responsibility. The ordering may need to change from time to time (as new handlers are added / some are no longer needed / handler responsibilities evolve / etc.).
  • Why use the declarative project item ordering instead of some imperative C# code: Project item order has recently been given UI support (although there is further work to be done). The SortByDisplayOrder project capability provides support for ordering project tree nodes in VS according to their project item ordering in the .csproj file, and for re-ordering those project items using 'Move up' and 'Move down' commands exposed by the Solution Explorer.
  • Why put the handlers in separate assemblies in the first place: Separating the 'handlers' into assemblies provides easy reuse in other projects that can compose and chains these handlers quickly and easily. The handlers themselves may be non-trivial, and deserve to be separate projects.

All in all, this means that the behaviour of the 'chain of responsibilities' is apparent simply by peeking at the composing project in the solution explorer, and that is also where the developer performs the reordering, at the click of a button / tap of the keyboard ↑ ↓. It's also naturally where the developer can add and remove handlers, and pull them into other composing projects.

Note: SortByDisplayOrder doesn't quite work out-of-the-box for the reference tree, but this enhancement can be provided fairly simply with a custom VSIX extension

@AR-May AR-May added the triaged label Feb 21, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

4 participants