2011-12-05 34 views
25

Có cách nào để buộc trình biên dịch giới hạn việc sử dụng thuộc tính tùy chỉnh chỉ được sử dụng trên các thuộc tính cụ thể như int, short, string (tất cả các kiểu nguyên thủy) không?
tương tự với AttributeUsageAttribute 's ValidOn- AttributeTargets điều tra.Cho phép một thuộc tính tùy chỉnh chỉ trên loại cụ thể

+0

Không, điều này là không thể. Nhất bạn có thể làm là viết một bài kiểm tra đơn vị sử dụng phản ánh và xác nhận việc sử dụng nó. Nhưng không có gì trong trình biên dịch sẽ làm điều này. – Amy

+0

; bạn không thể thêm các thuộc tính vào các lớp ngoài tầm kiểm soát của bạn * anyway * - vì vậy bạn không thể thêm các thuộc tính vào 'int' hoặc' string'. Bạn có nghĩa là "chỉ cho các thuộc tính * là *' int' hoặc 'chuỗi'"? nếu vậy, câu trả lời vẫn là "không", p –

+0

@MarcGravell ofcourse Tôi int, thuộc tính chuỗi và không thay đổi lớp int, Nhưng tôi sẽ chỉnh sửa. cảm ơn cho câu trả lời. – gdoron

Trả lời

21

Không, bạn không thể, về cơ bản. Bạn có thể giới hạn số điện thoại này thành structclass so với interface, tức là về nó. Ngoài ra, bạn không thể thêm thuộc tính vào các loại bên ngoài mã của mình (ngoại trừ thông qua TypeDescriptor, không giống nhau).

4

Bạn có thể tự viết mã để thực thi đúng cách sử dụng lớp thuộc tính của bạn, nhưng đó là nhiều như bạn có thể làm.

+5

lưu ý phụ: một thuộc tính không có quyền truy cập vào bối cảnh riêng của nó, vì vậy bất kỳ kiểm tra ở đây sẽ phải ở trong mã phản chiếu mà truy vấn cho thuộc tính –

+1

Tôi đã viết một bài kiểm tra đơn vị (NUnit) một khi được sử dụng Cecil xác minh thuộc tính "cho phép" của tôi. – Amy

+0

Thời gian tốt ..... –

4

Bạn có thể chạy kiểm tra đơn vị này để kiểm tra.

Thứ nhất, tuyên bố thuộc tính validation PropertyType:

[AttributeUsage(AttributeTargets.Class)] 
    // [JetBrains.Annotations.BaseTypeRequired(typeof(Attribute))] uncomment if you use JetBrains.Annotations 
    public class PropertyTypeAttribute : Attribute 
    { 
     public Type[] Types { get; private set; } 

     public PropertyTypeAttribute(params Type[] types) 
     { 
      Types = types; 
     } 
    } 

Tạo đơn vị kiểm tra:

[TestClass] 
    public class TestPropertyType 
    { 
     public static Type GetNullableUnderlying(Type nullableType) 
     { 
      return Nullable.GetUnderlyingType(nullableType) ?? nullableType; 
     } 

     [TestMethod] 
     public void Test_PropertyType() 
     { 
      var allTypes = AppDomain.CurrentDomain.GetAssemblies().SelectMany(a => a.GetTypes()); 
      var allPropertyInfos = allTypes.SelectMany(a => a.GetProperties()).ToArray(); 

      foreach (var propertyInfo in allPropertyInfos) 
      { 
       var propertyType = GetNullableUnderlying(propertyInfo.PropertyType); 
       foreach (var attribute in propertyInfo.GetCustomAttributes(true)) 
       { 
        var attributes = attribute.GetType().GetCustomAttributes(true).OfType<PropertyTypeAttribute>(); 
        foreach (var propertyTypeAttr in attributes) 
         if (!propertyTypeAttr.Types.Contains(propertyType)) 
          throw new Exception(string.Format(
           "Property '{0}.{1}' has invalid type: '{2}'. Allowed types for attribute '{3}': {4}", 
           propertyInfo.DeclaringType, 
           propertyInfo.Name, 
           propertyInfo.PropertyType, 
           attribute.GetType(), 
           string.Join(",", propertyTypeAttr.Types.Select(x => "'" + x.ToString() + "'")))); 
       } 
      } 
     } 
    } 

thuộc tính của bạn, ví dụ như cho phép các loại tài sản duy nhất chữ số thập phân: mô hình

[AttributeUsage(AttributeTargets.Property)] 
    [PropertyType(typeof(decimal))] 
    public class PriceAttribute : Attribute 
    { 

    } 

Ví dụ:

public class TestModel 
{ 
    [Price] 
    public decimal Price1 { get; set; } // ok 

    [Price] 
    public double Price2 { get; set; } // error 
} 
Các vấn đề liên quan