2013-04-04 21 views
5

Dưới đây là một đoạn của một lớp tôi sử dụng cho phương pháp mở rộng thử nghiệm Loại:Gọi một phương pháp khuyến nông chung mà không chỉ định như nhiều loại

class Something 
{ 
    [StringLength(100, MinimumLength = 1, ErrorMessage = "Must have between 1 and 100 characters")] 
    public string SomePublicString { get; set; } 
} 

tôi có phương pháp mở rộng sau:

public static class TypeExtensions 
{ 
    public static TAttributeType GetCustomAttribute<T, TAttributeType, TProperty>(this T value, Expression<Func<T, TProperty>> propertyLambda, bool inherit = false) 
    { 
    var type = typeof(T); 
    var member = (MemberExpression)propertyLambda.Body; 
    var propertyInfo = (PropertyInfo)member.Member; 
    var customAttributes = propertyInfo.GetCustomAttributes(typeof(TAttributeType), inherit); 

    return customAttributes.OfType<TAttributeType>().FirstOrDefault(); 
    } 
} 

Cách sử dụng trong thử nghiệm đơn vị:

1: var something = new Something(); 
2: var actual = something.GetCustomAttribute<Something, StringLengthAttribute, string>(x => x.SomePublicString); 

3: actual.MinimumLength.Should().Be(1); 
4: actual.MaximumLength.Should().Be(100); 
5: actual.ErrorMessage.Should().Be("Must have between 1 and 100 characters"); 

Trả lại này một bài kiểm tra vượt qua (sử dụng FluentAssertions).

Tuy nhiên, tôi muốn để có được các cuộc gọi phương pháp để GetCustomAttribute() trong dòng 2 xuống như sau:

var actual = something.GetCustomAttribute<StringLengthAttribute>(x => x.SomePublicString); 

Đây có phải là có thể? Tui bỏ lỡ điều gì vậy? Có lẽ tôi đang gặp tai nạn caffeine. :(

Trả lời

7

Không, bạn phải chỉ định tất cả đối số loại hoặc không có đối số nào. Không có suy luận kiểu "một phần". Tuy nhiên, một cách bạn có thể tránh được với điều này là có một phương thức chung với một đối số kiểu duy nhất trả về một cá thể của một lớp chung, và sau đó sử dụng suy luận kiểu trên đó để làm phần còn lại - hoặc ngược lại . Trong trường hợp này, nó có thể thực sự là tốt nhất để tách các thuộc tính lấy từ phần còn lại anyway:

something.GetPropertyAttributes(x => x.SomePublicString) 
     .FirstAttribute<StringLengthAttribute>(); 

Đây là phương pháp gọi đầu tiên suy luận TTProperty - và chỉ cần trả về một IEnumerable<Attribute>FirstAttribute sẽ chỉ làm OfType/FirstOrDefault cuộc gọi. (Bạn thậm chí có thể quyết định rằng bạn không cần FirstAttribute, vì nó khá đơn giản để gọi OfTypeFirstOrDefault chính mình.)

+1

Huzzah cho Nguyên tắc chịu trách nhiệm duy nhất. – StriplingWarrior

+0

Cảm ơn. Ban đầu tôi đã có một cái gì đó giống như mẫu mã của bạn, phá vỡ sự phản ánh 'PropertyInfo', phản xạ thuộc tính tùy chỉnh, và cuối cùng, loại tôi muốn, nhưng đã hy vọng cho một cái gì đó ... leaner. :-) –

+0

@Dan, tôi thường nghe rằng khiếu nại áp dụng cho giải pháp này và chưa bao giờ thực sự hiểu được nó đến từ đâu.Có vẻ khá nạc với tôi (đối với người tiêu dùng). –

3

Nó không phải là có thể suy ra một số, nhưng không phải tất cả các đối số loại, không

Bạn có thể:.

  1. Xác định tất cả các tham số chung

  2. .
  3. Đảm bảo rằng tất cả các đối số chung có thể được suy ra. (Không phải lúc nào cũng có thể, hoặc các thỏa hiệp cần thiết để cho phép suy luận có thể không được mong muốn.)

  4. Phá vỡ phương thức này thành nhiều phương thức sao cho một phương thức đưa vào các đối số chung và một phương thức thì không.

+0

Cảm ơn. Phương pháp mở rộng của tôi không có loại mặc dù, vì tôi phải chỉ định tất cả các loại được sử dụng. Đây có phải là 'sạch' vì tôi có thể gọi phương thức không? –

+1

@DanAtkinson Không thay đổi chữ ký của phương thức, vâng. Như tôi đã nói, suy luận là một điều tất cả hoặc không có gì. – Servy