Giter Site home page Giter Site logo

vstools.projects's Introduction

Introduction

VsTools.Projects is a set of wrapper classes around XDocument for reading and modifying the contents of Visual Studio C# Project (.csproj) files.

It grew out of a need to programatically insert generated source files into a project.

VsTools.Projects only abstracts the most common elements, as the format is completely extensible and can contain custom elements specific to a third-party assembly.

The API and documentation are currently a work in progress, so expect some changes as the project progresses.

NuGet

PS> Install-Package VsTools.Projects

Usage

There are two types of .csproj format. The pre-2017 format was the format used by older .NET Framework projects and has the following root element:

<Project ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">

The 2017 format is the format introduced by Visual Studio 2017 for newer .NET Framework projects and .NET Core and has the following root element:

<Project Sdk="Microsoft.NET.Sdk">

The newer format takes advantage of a lot of default values, and by assuming that all files in the path and sub-paths are part of the project reduces the size of the project file signigicantly.

VsTools.Projects can read and modify both, but will not validate the contents based on the expected format. It is up to you to make sure you are using the correct elements and attributes.

Make sure you understand the schema or element hierarchy.

Loading an existing Project

To load an existing project, use Project.Load. The property Is2017Project will be true if the root element has the attribute Sdk.

var project = new Project.Load("path\\to\\project.csproj");

var isNewVersion = project.Is2017Project;

Adding a file for compilation to a Project

To add a .cs file to a .csproj, you need to add a Compile element to a new or existing ItemGroup element.

var project = Project.Load("path\\to\\project.csproj");

var itemGroup = new ItemGroup();

var newFile = new Compile("path\\to\\file.cs");

itemGroup.AddContent(newfile);

project.Add(itemGroup);

project.Save();

This will insert the following xml as the last child of the Project element.

  <ItemGroup>
    <Compile Include="path\to\file.cs"/>
  </ItemGroup>

PropertyGroup

The PropertyGroup element stores project properties such as PlatformTarget, OutputType, AssemblyName, TargetFrameworkVersion to name a few, as well as other custom properties.

Accessing PropertyGroup Properties

PropertyGroup element propeties can be accessed through the PropertyGroup.Properties collection. Properties are of type StringPropertyType which allow you to set a Condition.

var debug = project.PropertyGroups.First(x => x.Condition == " '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ");

Console.WriteLine(debug.Properties["DebugSymbols"].Value);

Getting and Setting PropertyGroup Properties

The PropertyGroup class provides convenience methods GetProperty and SetProperty which avoids having to go through a StringPropertyType.

GetProperty returns the string value or null if the property does not exist.

propertyGroup.GetProperty("Configuration");\

SetProperty is overloaded with a parameter to set a Condition attribute on the property. Setting a property value to null will remove the property element.

// Set the property 'Configuration' to 'Debug' with a condition
propertyGroup.SetProperty("Configuration", "Debug", " '$(Configuration)' == '' ");
// Set the property 'OutputType' to 'Exe'
propertyGroup.SetProperty("OutputType", "Exe");
// Remove property 'SccLocalPath'
propertyGroup.SetProperty("SccLocalPath", null);

Setting a property can also be done through the PropertyGroup.Properties collection.

debug.Properties["DebugSymbols"] = new Property("Configuration", "Debug") { Condition = " '$(Configuration)' == '' " };

ItemGroup and Item

An ItemGroup contains a collection of Item objects, which define inputs into the build system.

Common items are Reference, Compile, Resource, and None, which tell the build system how to handle the specified item.

Items should inherit from the Item class. Items have a required Include attribute, and 0 or more Item Metadata that are usually encoded as child elements, for example, a Reference can have a HintPath

var references = new ItemGroup();

var reference = new Reference("Newtonsoft.Json, Version=11.0.0.0, Culture=neutral, PublicKeyToken=30ad4fe6b2a6aeed, processorArchitecture=MSIL");

reference.HintPath = "..\\packages\\Newtonsoft.Json.11.0.1\\lib\\net45\\Newtonsoft.Json.dll";

reference.Private = "True";

references.Add(reference);

var files = new ItemGroup();

var file = new Compile("path\\to\\class.cs");

file.DependentUpon = "path\\to\\page.cshtml";

files.Add(file);

project.Add(references);
project.Add(files);

This will generate the following XML.

  <ItemGroup>
    <Reference Include="Newtonsoft.Json, Version=11.0.0.0, Culture=neutral, PublicKeyToken=30ad4fe6b2a6aeed, processorArchitecture=MSIL">
      <HintPath>..\packages\Newtonsoft.Json.11.0.1\lib\net45\Newtonsoft.Json.dll</HintPath>
      <Private>True</Private>
    </Reference>
  </ItemGroup>
  <ItemGroup>
    <Compile Include="path\to\class.cs"/>
      <DependentUpon>page.cshtml</DependentUpon>
    </Compile/>
    <Content Include="path\to\page.cshtml" />
  </ItemGroup>

Item Metadata

For convenience, known Metadata for an element are exposed as string properties on the Item implementation, e.g. Reference has a HintPath property as shown above.

It is possible to add custom metadata using AddOrUpdateMetadataValue on a class inheriting from Item, or SetMetadata or AddMetadata on any class inheriting from ProjectElement.

Conditions

In MSBuild, Conditions allow for conditional compilation based on defined project properties and other user defined conditions. Conditions are implemented as a Condition attribute on most elememts. Setting a condition on an ItemGroup for example will cause items under that item group to be added only if the condition is met.

All classes that inherit from ProjectElement have a Condition property that sets the underlying element's Condition attribute.

The following will cause the itemGroup's items to be included during compilation if the Debug configuration is specified.

itemGroup.Condition = " '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ";

In order to set a Condition attribute on an item Metadata, ensure that the Metadata has been created by setting it through the property, then access the Metadata as a Property through the items Metadata collection property

reference.Metadata["Project"].Condition = " '${CustomProperty}' == 'CustomValue' ";

vstools.projects's People

Contributors

rupertavery avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar

vstools.projects's Issues

Creating new ProjectReference gives exception

When trying to create a new ProjectReference using: new ProjectReference("../classlibrary/classlibrary.csproj", "project", "classlibrary") gives a NullReferenceException in ItemGroupContent.ElementName.

Any new type of document not supported will cause error.

My .csproj file contained a line of type EmbeddedResource. Since the library does not have support for this type, the enumeration of Contents instantly throws an error "Item not found in Dictionary". This could be solved by adding a class EmbeddedResource but more unsupported types can come up.

ItemGroup 'Folder' missing

Given the following project file, I get a "The given key was not present in the dictionary." exception when I ask for the Contents of an ItemGroup:

<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
  <PropertyGroup>
    <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
    <ProjectGuid>{E90B1572-820F-4581-9351-DB36703E6846}</ProjectGuid>
    <AppDesignerFolder>Properties</AppDesignerFolder>
    <RootNamespace>Test</RootNamespace>
    <AssemblyName>Test</AssemblyName>
  </PropertyGroup>
  <ItemGroup>
    <Folder Include="Properties\" />
  </ItemGroup>
  <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
</Project>

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.