2012-03-01 15 views
15

Kontekst: Zarządzam dość dużym rozwiązaniem. Co jakiś czas ludzie dodają odniesienie DLL do projektu w rozwiązaniu, w którym powinni dodać odniesienie do projektu. W takim przypadku chcę ostrzec. Chcę to zrobić, znajdując wszystkie odwołania z "bin \ debug" w ich HintPath *. Wiem, że referencje są przedmiotami w ItemGroup, z metadanymi "HintPath".Używanie funkcji elementu w wartościach metadanych

spodziewałem się czegoś tak pracować:

<Warning Text="Reference %(Reference.Identity) should be a project reference. HintPath: %(Reference.HintPath)" 
     Condition="%(Reference.HintPath).IndexOf('bin\debug') != -1"/> 

wydaje się jednak to, że nie można korzystać z funkcji ciąg IndexOf tak. Próbowałem wielu permutacji powyższych, bez powodzenia.

  • Edycja: wiem, że ten czek nie jest w pełni dowodowy, ale chcę po prostu zmniejszyć szczere błędy.

Odpowiedz

18

Korzystanie MSBuild 4,0 Property Functions jest to możliwe do zrobienia porównania ciągów:

<Target Name="AfterBuild"> 

    <Message Text="Checking reference... '%(Reference.HintPath)'" Importance="high" /> 

    <Warning Text="Reference %(Reference.Identity) should be a project reference. HintPath: %(Reference.HintPath)" 
      Condition="$([System.String]::new('%(Reference.HintPath)').Contains('\bin\$(Configuration)'))" /> 

</Target> 
+1

+1: Byłem tak bardzo zainteresowany uzyskaniem własności z metadanych przedmiotu, że nie widziałem tej oczywistej rzeczy. W rzeczywistości, biorąc pod uwagę twoją konkretną potrzebę, wygląda to znacznie lepiej. –

+0

Działa dla mnie. Żałuję, że nie mogę rozróżniać wielkości liter - IndexOf ('\ bin \ $ (Konfiguracja)', StringComparison.OrdinalIgnoreCase) - ale MSBuild nie wydaje się być w stanie wywoływać funkcji z przeciążeniami. – Jonathan

+0

+1 Kiedy próbowałem rozwiązać problem przez miself, myślałem o tym pomyśle, ale nie zdawałem sobie sprawy, jak utworzyć instancję obiektu string (właściwie nie jestem zbyt płynny w C#). Dzięki za rozwiązanie. –

2

pierwsze nie że składnia nie jest poprawna dla wywoływania funkcji, to muszą być:

%(Reference.HintPath.IndexOf(...))  # Note: not supported by MSBuild 

Jednak funkcje nieruchomości w MSBuild są not allowed metadanych elementu, tak że nie pomoże ty też.

Co można obejść, poprzez wywołanie oddzielnego celu, który jest w zasadzie nazywany dla każdego elementu.

<Target Name="CheckProjectReferences"> 
    <MSBuild 
     Projects="$(MSBuildProjectFullPath)" 
     Properties="Identity=%(Reference.Identity);HintPath=%(Reference.HintPath)" 
     Targets="_Warn"/> 
    </Target> 

    <Target Name="_Warn"> 
    <Warning Text="Reference $(Identity) should be a project reference. HintPath: $(HintPath)" 
      Condition="$(HintPath.IndexOf('bin\debug')) != -1"/> 
    </Target> 

Szczerze mówiąc, nie jestem pewien, czy to wystarczy, aby złapać wszystkie "naruszenia". Na przykład powyższe działa tylko dla bin\debug, ale nie dla bin\Debug lub innych odmian o różnych wielkościach liter, które są funkcjonalnie równoważne. Szukać dla nich, jak również, że trzeba wywołać przeciążenie IndexOf(string, StringComparison) jednak właśnie robi:

$(HintPath.IndexOf('bin\debug', System.StringComparison.OrdinalIgnoreCase)) 

nie będzie działać, ponieważ rozdzielczość przeciążenie MSBuild wzrośnie IndexOf(char, Int32) i daje ten błąd:

MSB4184: The expression ""bin\debug".IndexOf(bin\debug, System.StringComparison.OrdinalIgnoreCase)" cannot be evaluated. String must be exactly one character long.

Więc musisz przekonać go za pomocą przeciążenie IndexOf(String, Int32, Int32, StringComparison) bezpośrednio:

$(HintPath.IndexOf('bin\debug', 0, 9, System.StringComparison.OrdinalIgnoreCase)) 

Być może trzeba również sprawdzić, bin\Release lub inne odmiany. Nie jestem pewien, czy jest to najlepszy sposób, aby znaleźć odniesienie do projektu, ale jeśli znasz (i do pewnego stopnia kontrolować) swoje środowisko, to może być wykonalne.

+0

To wydaje się działać, choć muszę dodatkowy warunek odn bez HintPath. Jednak wywołanie msbuild dla każdego odwołania jest wolne - moje rozwiązanie spowalniało z 2 sekund do 34 sekund! Jeśli nie można tego zrobić w tej samej instancji msbuild, to nie jest to dla mnie warte. – Jonathan

+0

@ Jonathan błąkałam się, próbując znaleźć sposób na zrobienie tego w tej samej instancji MSBuilda, ale nie mogłem znaleźć (poza pisaniem własnego zadania). –

0

@ Christian.K ma rację w swojej analizie. Innym rozwiązaniem byłoby wymusić przeciążenie typu string używając &quot; dla cytatów:

<Warning 
    Text="..." 
    Condition="$(HintPath.IndexOf(&quot;bin\debug&quot;, System.StringComparison.OrdinalIgnoreCase)) != -1" />