2015-05-08 13 views
7

Tôi có thuộc tính tùy chỉnh mà tôi muốn hạn chế đối với các phương thức có loại trả về void.Tôi có thể hạn chế thuộc tính tùy chỉnh để làm trống chỉ các phương thức không?

Tôi biết tôi có thể giới hạn các phương pháp sử dụng [AttributeUsage(AttributeTargets.Method)] nhưng dường như không có cách nào để hạn chế kiểu trả về hoặc bất kỳ khía cạnh nào khác của chữ ký phương thức.

Thuộc tính [System.Diagnostics.Conditional] có chính xác loại giới hạn mà tôi muốn. Thêm nó vào một kết quả phương pháp phi khoảng trống trong các lỗi biên dịch:

The Conditional attribute is not valid on '(SomeMethod)' because its return type is not void

và IntelliSense nói:

Attribute 'System.Diagnostics.ConditionalAttribute' is only valid on attribute classes or methods with 'void' return type.

Nếu tôi F12 để các ConditionalAttribute tôi thấy rằng nó được trang trí với các thuộc tính sau:

[Serializable]
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Method, AllowMultiple = true)]
[ComVisible(true)]

Không ai trong số đó nói bất kỳ điều gì về loại trả lại.

Làm cách nào để thực hiện thuộc tính Conditional và tôi có thể làm tương tự cho thuộc tính tùy chỉnh của mình không?

+0

Có thể bạn sẽ tìm thấy điều này là nhiều hơn một chức năng như thế nào * sử dụng của nó * chứ không phải là như thế nào * tuyên bố của mình *. – Jamiec

+0

Hiện tại tôi không nghĩ rằng có thể, nguồn 'System.Diagnostics.ConditionalAttribute' không đáng kể trong hiệu ứng đó (http://www.dotnetframework.org/default.aspx/[email protected]/[email protected]/DEVDIV_TFS/Dev10/Phát hành/RTMRel/ndp/clr/src/BCL/Hệ thống/Chẩn đoán/ConditionalAttribute @ cs/1305376/ConditionalAttribute @ cs). Nó phải là một số phép thuật biên dịch. Rosalyn và C# 6 có thể thay đổi điều đó. –

Trả lời

4

Hóa ra trong trường hợp cụ thể của tôi có giải pháp vì tôi đang sử dụng PostSharp.

Thuộc tính tùy chỉnh của tôi kế thừa từ PostSharp.Aspects.MethodInterceptionAspect (được kế thừa từ Attribute) có phương thức CompileTimeValidate(MethodBase method) có thể ghi đè.

này cho phép phát ra lỗi biên dịch trong thời gian xây dựng:

public override bool CompileTimeValidate(MethodBase method) 
{ 
    Debug.Assert(method is MethodInfo); 
    var methodInfo = (MethodInfo)method; 

    if (methodInfo.ReturnType != typeof(void)) 
    { 
     Message.Write(
      method, SeverityType.Error, "CX0001", 
      "The Foo attribute is not valid on '{0}' because its return type is not void", 
      method.Name); 

     return false; 
    } 

    return true; 
} 
3

Hầu hết các thuộc tính chỉ đơn giản là siêu dữ liệu được gắn vào các lớp và có thể được kiểm tra khi chạy. Tuy nhiên, một số thuộc tính được trình biên dịch sử dụng. Ví dụ: System.ObsoleteAttribute có thể được sử dụng để trình biên dịch phát ra lỗi hoặc cảnh báo nếu phương thức, lớp, v.v. được sử dụng. System.Diagnostics.ConditionalAttribute là một ví dụ khác về thuộc tính được trình biên dịch sử dụng. Như vậy, trình biên dịch tự do áp đặt các quy tắc về việc sử dụng nó mà không thể áp dụng cho các thuộc tính khác (chẳng hạn như các phương thức void).

Thật không may, tại thời điểm này, không thể ảnh hưởng đến trình biên dịch mặc dù thuộc tính tùy chỉnh. Với Rosalyn được viết bằng C#, cách này được mở ra để có mã chạy trình biên dịch trong thuộc tính như là một phần của giai đoạn biên dịch. Ví dụ về hạn chế của bạn một thuộc tính để làm mất hiệu lực các phương thức sẽ là một trong những cách sử dụng tính năng này, nếu nó được thực hiện.

+1

Cảm ơn câu trả lời của bạn! Tôi đã chấp nhận nó nhưng tôi thực sự tìm thấy một giải pháp bằng cách sử dụng postsharp (mà tôi đã sử dụng anyway). Xem câu trả lời của riêng tôi để biết chi tiết. –

+0

Rất hay, nhờ @RomanReiner để cập nhật. –

Các vấn đề liên quan