2010-09-23 34 views
5

Tôi có một đối tượng (biểu mẫu) chứa một tập hợp (.Fields) mà tôi muốn chứa các phiên bản của một lớp chung chung (FormField).Bộ sưu tập các loại chung

Các FormField, đơn giản, được định nghĩa như vậy:

public class FormField<T> 
{ 
    private Form Form; 
    public T Value { get; set; } 
    public string Name { get; set; } 

    public void Process() 
    { 
     // do something 
    } 

    public FormField(Form form, string name, T value) 
    { 
     this.Name = name; 
     this.Value = value; 
     this.Form = form; 
    } 
} 

này cho phép tôi để có FormField, FormField vv và phần đó hoạt động tuyệt vời. Những gì tôi muốn là một bộ sưu tập của "Formfields" không phụ thuộc vào chủng loại, nhưng tôi buộc phải xác định một kiểu (có vẻ như) như:

public class Form 
{ 

    string Code { get; set; } 
    string Title { get; set; } 
    int Year { get; set; } 
    Guid ClientID { get; set; } 

    ICollection<FormField<int>> Fields { get; set; } 
} 

gì, tôi nghĩ rằng, tôi muốn là một giao diện cho phép tôi để tóm tắt các loại thông tin và do đó gõ bộ sưu tập như trường hợp của (ví exxample) IFormField không FormField <>

Nhưng tôi không thể nhìn thấy làm thế nào để xác định này mà không cần gõ mạnh việc thu thập trong giao diện ...

Bất kỳ trợ giúp nào (bao gồm mọi giải pháp thay thế!) Sẽ được đánh giá cao!

Cảm ơn, Ben

Trả lời

4

Tạo một giao diện hay lớp cơ sở không chung chung, mà có lẽ bao gồm mọi thứ FormField không trừ các bit loại cụ thể. Sau đó, bạn có thể có một ICollection<IFormField>. Rõ ràng là bạn sẽ không thể sử dụng điều này theo cách được đánh máy mạnh, về loại trường đang được sử dụng - nhưng bạn có thể sử dụng tất cả các bit không thuộc loại cụ thể của nó (ví dụ: tên và biểu mẫu).

+1

cảm ơn Jon, nhưng nếu tôi hiểu bạn một cách chính xác thì giao diện sẽ có hiệu quả mọi thứ nhưng thuộc tính giá trị, vốn là yếu tố then chốt của FormField ..? Tôi đang cố gắng sử dụng Generics theo cách sai? – Ben

+1

@Ben: Hãy xem xét cách bạn sẽ cố gắng * sử dụng * bộ sưu tập này. Nó có thể có một hỗn hợp các kiểu trường biểu mẫu khác nhau (int, string, v.v.). Làm thế nào bạn sẽ cố gắng sử dụng các giá trị từ các trường biểu mẫu trong 'Biểu mẫu'? Bạn sẽ không biết chúng tại thời gian biên dịch, hoặc bạn sẽ được đúc một cách rõ ràng đến đúng loại. –

+0

@Ben, bạn có thể khai báo thuộc tính Value trong giao diện IFormField, nhưng bạn sẽ phải khai báo nó là Object. Trong lớp FormField , khai báo giá trị là T và triển khai IFormField.Value một cách rõ ràng. –

9

Dưới đây là một số mã để hoàn Jon của câu trả lời:

public interface IFormField 
{ 
    string Name { get; set; } 
    object Value { get; set; } 
} 

public class FormField<T> : IFormField 
{ 
    private Form Form; 
    public T Value { get; set; } 
    public string Name { get; set; } 

    public void Process() 
    { 
     // do something 
    } 

    public FormField(Form form, string name, T value) 
    { 
     this.Name = name; 
     this.Value = value; 
     this.Form = form; 
    } 

    // Explicit implementation of IFormField.Value 
    object IFormField.Value 
    { 
     get { return this.Value; } 
     set { this.Value = (T)value; } 
    } 
} 

Và trong hình của bạn:

ICollection<IFormField> Fields { get; set; } 
0

Một tùy chọn khác (một thay thế cho Jon's answer) là áp dụng các adapter pattern, có thể hữu ích khi:

  • bạn không thể mod ify loại, và do đó có thể không xác định một loại cơ sở cho nó.
  • hoặc, cần phải hiển thị 'các loại bit cụ thể' (khi Jon đặt nó).

Khi bạn muốn để lộ loại cụ thể bit, bạn có hiệu quả have to create a non-generic wrapper. Một ví dụ nhỏ:

class NonGenericWrapper<T> : IAdaptor 
{ 
    private readonly Adaptee<T> _adaptee; 

    public NonGenericWrapper(Adaptee<T> adaptee) 
    { 
     _adaptee = adaptee; 
    } 

    public object Value 
    { 
     get { return _adaptee.Value; } 
     set { _adaptee.Value = (T) value; } 
    } 
} 

Thực hiện điều này hành vi không chung trong một căn cứ kiểu cách hiệu quả sẽ phá vỡ Liskov substitution principle, đó là lý do tôi thích cách tiếp cận wrapper như I also argue in my blog post.

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