9

(Basically we want to import targets files at some places in the *.csproj file and otherwise check that the file follows our standards)

What is the best way of doing this? I am planning to use C# and XDocument (LINQ to XML) and manipulated the nodes. But is that the best way? Other alternates may be:

  1. Find the XSD for csproj/msbuild and create stronly typed objects that represent the project file. is this possible?
  2. Are there other tools/languages that are better (It could use this as an excuse to learn Ruby). An answer would have to have some links to examples for manipulating XML.

Maybe the real question is: What is the best way to read and manipulate XML programatically?

Arve
  • 6,977
  • 5
  • 35
  • 39
  • Your best option would be to use some kind of VS automation. You really should not be messing with those files directly. –  Feb 05 '10 at 08:20
  • 5
    @Moron: I don't see why not. They're basically MSBuild files. IMO the whole *point* of them being XML (instead of them being opaque binary files) is that they're editable. – Jon Skeet Feb 05 '10 at 08:29
  • 1
    @Jon Ideally I wouldn't say 'editable'. Readable, sure. But editing them could be problematic say, when they upgrade to a new version of VS. Unless we're talking really simple changes. – kprobst Feb 05 '10 at 08:32
  • Well, (I think) I have seen incompatibility between versions. You don't want your code to break when the next version comes out. Perhaps I am confusing between different file types. Anyway, if VS provides some way to manipulate them, why not use it? (Not that I am saying VS provides a way...). –  Feb 05 '10 at 08:33
  • 2
    @Moron: I'd rather change the LINQ to XML code 1000 times before working with the VS API again. – codekaizen Feb 05 '10 at 08:36
  • @codekaizer: You can always blame Microsoft when your (shipped) code breaks :-) –  Feb 05 '10 at 08:38
  • Strange. Up votes to comments encouraging bad practices! Don't flame me. I understand that there might be no other option. –  Feb 05 '10 at 09:16
  • @Moron: Have you considered that the upvotes may be because your idea of "bad practise" isn't the same as everyone else's? – Jon Skeet Feb 05 '10 at 09:38
  • Yes, I understand it is a subjective term, and completely depends on the situation/context. Relying on undocumented features (which might potentially break you) is unlikely to be a good practise in most scenarios, though. –  Feb 05 '10 at 16:15

4 Answers4

7

I would personally just use LINQ to XML directly... unless you're doing really heavy processing, I don't think it would be worth creating an object model for it. Just how many rules/whatever do you need for this tool?

Jon Skeet
  • 1,261,211
  • 792
  • 8,724
  • 8,929
5

MSBuild (which is the format of project files) has an object model that you can use for applications such as this.

Sayed Ibrahim Hashimi
  • 42,483
  • 14
  • 139
  • 172
  • I think you are on the correct path. If only you've been more specific on how to do it... Maybe http://msdn.microsoft.com/en-us/library/microsoft.build.buildengine.project_members(VS.80).aspx ? – Alfred Myers Feb 05 '10 at 16:56
3

We have an in-house tool that manipulates project files on the fly to update references and set various properties. Since project files are not that complicated, we simply manipulate the XML directly. The tool was written long before LINQ was available, so it doesn't use it, but I see no reason why you couldn't do what Jon's suggesting.

When we upgraded from VS2005 to VS2008 we only had to do minor adjustments to the code, but of course there's no guarantees in that regard. We may have to do bigger adjustments for future versions.

If you're interested, there's a bit more info on our tool in my answer to this question Should a .sln be committed to source control?

Community
  • 1
  • 1
Brian Rasmussen
  • 109,816
  • 33
  • 208
  • 305
  • We also use this system for our project files. Seems to work well and no VS dependencies, which is a plus for the build machine. – Pondidum Feb 05 '10 at 09:07
2

As per second part of our question how to manipulate XML programatically, here is some xml from a project configuration file. (web.config)

 <system.web>
<compilation debug="false">
<assemblies>
        <add assembly="System.Core, Version=3.5.0.0, Culture=neutral, PublicKeyToken=B77A5C561934E089" />
        <add assembly="System.Web.Extensions, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35" />
        <add assembly="System.Web.Abstractions, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35" />
        <add assembly="System.Web.Routing, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35" />
        <add assembly="System.Web.Mvc, Version=1.0.0.0, Culture=neutral, 
</compilation>
</compilation>

and to parse using LINQ-TO-XML, something like follows

XDocument assemblies = XDocument.Parse("web.config");

var projectAssemblies= from a in assemblies.Descendants("system.web\assemblies")
               select new  // What ever object you waant
               {
                   Assembly = a.Attribute("assembly").Value.ToString(),
                   Version = a.Attribute("Version").Value.ToString(),
                   Culture = a.Element("Culture").Value.ToString(),
                   PublicKeyToken = a.Attribute("PublicKeyToken").Value.ToString()
               };

foreach (var v in projectAssemblies)
{
    // enjoy them 
}

hope it helps

Asad
  • 19,788
  • 16
  • 65
  • 91