- | rssFeed | My book on MSBuild and Team Build | Archives and Categories Thursday, 21 October 2010

MSBuild: Filter list take 2

Last night I saw this tweet.

@MikeFourie MSBuild Q: given I have @(ProjectOutputs) how can I get a collection of all *.Unit.dll files?

About a year ago I blogged about inline tasks including a FilterList task. So for his case the FilterList would work, but then I was thinking that he should be able to do this with some of the goodness that was released wtih MSBuild 4.0. Specifically with Property Function and Item Functions. So I thought about it and whipped up a quick example.

Take a look at the file below.



  
    
    
  
  
  
        
    
      
    
    
  

In this file I have created a dummy item named TargetOutputs and populated it with a bunch of fake assembly names. Then inside the Demo target, I print out the items in that list and construct another item list, UnitTestAssemblies. In this declaration I am including %(TargetOutputs.Identity) with the condition '@(TargetOutputs->Contains("unit"))'=='True'. Let me break this down for you a bit. With Item Functions there is a specific set of functions that you can call like DirectoryName/Metadata/Distinct/etc (see below for the reference link for full list), but you can also execute any string instance method. What you need to understand is that it will execute the method for all items in the list then return a new list with the invocation result. Essentially these are a new form of Item Transformations. I didn’t want to handle these in bulk, I need to apply the filter to each individual item value. In order to do that I use the %(TargetOutputs.Identity) which kicks batching in. Since I can see that the values in the include value are unique I know that the Identity metadata is unique. So what that means is When I do something like the message task will be invoked once per item value in TargetOutputs. The same goes for the item declaration. So in the UnitTestAssemblies item group declaration I can use a condition of Condition='@(TargetOutputs->Contains("unit"))'=='True' , because we are know that @(TargetOutputs) will only have 1 value per invocation. With that condition I only added files that have unit in the name. When you execute the Demo target the result is shown below.

image

Pretty cool huh? The best part, I managed to fit my reply in 140 characters in this tweet.

@HowardvRooijen

Anywayz, if you are not following me on twitter you can find me at @sayedihashimi.

Resources

Sayed Ibrahim Hashimi

msbuild | MSBuild 4.0 Thursday, 21 October 2010 07:11:11 (GMT Daylight Time, UTC+01:00)  #     |