2012-03-01 21 views
15

Bối cảnh: Tôi quản lý một giải pháp khá lớn. Thường xuyên, mọi người thêm một tham chiếu DLL vào một dự án trong giải pháp mà họ nên thêm một tham chiếu dự án. Tôi muốn đưa ra cảnh báo trong trường hợp này. Tôi muốn làm điều đó bằng cách tìm tất cả các tham chiếu với 'bin \ debug' trong HintPath * của họ. Tôi biết rằng tài liệu tham khảo là các mục trong ItemGroup, với siêu dữ liệu "HintPath".Sử dụng chức năng Mục trên giá trị siêu dữ liệu

tôi mong đợi một cái gì đó như thế này để làm việc:

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

Tuy nhiên, có vẻ như tôi không thể sử dụng chức năng chuỗi IndexOf như thế. Tôi đã thử nhiều hoán vị ở trên, không thành công.

  • Chỉnh sửa: Tôi biết kiểm tra này không đầy đủ, nhưng tôi chỉ muốn giảm sai lầm trung thực.

Trả lời

18

Sử dụng MSBuild 4,0 Property Functions nó có thể làm so sánh chuỗi:

<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: Tôi đã quá quen thuộc với việc nhận được một tài sản từ siêu dữ liệu mục, rằng tôi không thấy điều rõ ràng này. Trên thực tế, với nhu cầu cụ thể của bạn, điều này có vẻ tốt hơn nhiều. –

+0

Làm việc cho tôi. Tôi muốn tôi có thể làm tra cứu không phân biệt dạng chữ - IndexOf ('\ bin \ $ (Cấu hình)', StringComparison.OrdinalIgnoreCase) - nhưng MSBuild dường như không thể gọi các hàm có quá tải. – Jonathan

+0

+1 Khi tôi đang cố gắng giải quyết vấn đề bằng chính mình, tôi đã nghĩ về ý tưởng này, nhưng không nhận ra, làm thế nào để tạo ra đối tượng chuỗi (thực ra, tôi không quá thông thạo C#). Cảm ơn các giải pháp. –

2

đầu tiên không phải là cú pháp của bạn là không chính xác cho cách gọi chức năng, nó sẽ cần phải:

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

Tuy nhiên, chức năng sở hữu trong MSBuild là not allowed trên mục siêu dữ liệu, vì thế nó sẽ không giúp bạn.

Những gì bạn có thể làm việc xung quanh điều này, bằng cách gọi một mục tiêu riêng biệt về cơ bản được gọi cho mọi mục.

<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> 

Thành thật mà nói, tôi không chắc liệu điều đó có đủ để bắt tất cả "vi phạm" hay không. Ví dụ: ở trên sẽ chỉ hoạt động cho bin\debug, nhưng không hoạt động đối với bin\Debug hoặc các biến thể hỗn hợp khác có chức năng tương đương. Để tìm kiếm họ là tốt, bạn cần phải gọi tình trạng quá tải IndexOf(string, StringComparison), tuy nhiên chỉ thực hiện:

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

Sẽ không làm việc, bởi vì độ phân giải quá tải MSBuild sẽ đón IndexOf(char, Int32) và cung cấp cho bạn lỗi này:

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

vì vậy, bạn sẽ cần phải thuyết phục nó bằng cách sử dụng quá tải IndexOf(String, Int32, Int32, StringComparison) trực tiếp:

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

bạn có thể cũng cần phải kiểm tra bin\Release hoặc các biến thể khác. Tôi không chắc nếu đó là cách tốt nhất để tìm ra một tham chiếu nên là một tài liệu tham khảo dự án, nhưng nếu bạn biết (và một điều khiển mở rộng nhất định) môi trường của bạn nó có thể là khả thi.

+0

Điều này dường như làm việc, mặc dù tôi cần một điều kiện bổ sung cho refs mà không HintPath. Tuy nhiên, gọi msbuild cho mỗi tham chiếu là chậm - giải pháp của tôi bị chậm lại từ 2 giây đến 34 giây! Nếu không có cách nào để làm điều đó trong cùng một trường hợp msbuild, thì nó không đáng cho tôi. – Jonathan

+0

@ Jonathan Tôi đang đùa giỡn, cố gắng tìm cách để làm điều đó trong cùng một cá thể MSBuild, nhưng không thể tìm thấy bất kỳ (viết tắt nhiệm vụ của riêng bạn có thể). –

0

@ Christian.K là đúng trong phân tích của ông. Một giải pháp khác sẽ là để buộc các tình trạng quá tải kiểu string sử dụng &quot; cho các dấu ngoặc kép:

<Warning 
    Text="..." 
    Condition="$(HintPath.IndexOf(&quot;bin\debug&quot;, System.StringComparison.OrdinalIgnoreCase)) != -1" /> 
Các vấn đề liên quan