2009-06-17 10 views
9

Tôi thường thấy mình trong tình huống mà tôi tạo một giao diện chung hoặc lớp và sau đó muốn sử dụng các phiên bản khác nhau của lớp hoặc giao diện này theo cách không chung chung. Ví dụ: tôi có thể có một giao diện như sau:Phiên bản không chung của các lớp và giao diện chung

interface ICanCreate<T> 
{ 
    T NewObject(); 
} 

Điều này cho phép một lớp là nhà máy cho loại đó. sau đó tôi muốn đăng ký những việc này với một lớp nhà máy nói chung, vì vậy tôi cố gắng viết một cái gì đó như thế này:

public class Factory 
{ 
    private Dictionary<Type, ICanCreate> mappings; // what do I put here???? 

    public void RegisterCreator<T>(ICanCreate<T> creator) 
    {    
    } 

    public T Create<T>() 
    {    
    } 
} 

Trong từ điển loại nào để tôi sử dụng cho giá trị của tôi không? Tôi không biết nếu tôi thiếu một số loại nguyên tắc thiết kế và tôi biết rằng điều này có rất nhiều để làm với co (ntra?) Phương sai. Bất kỳ trợ giúp hoặc ý tưởng nào sẽ được đánh giá cao.

Trả lời

11

Bạn có phải chỉ cần sử dụng object trong tuyên bố từ điển của bạn (đó là tất cả tư nhân, và bạn có thể xác minh rằng bạn sẽ không bao giờ đặt các loại sai điều trong đó) hoặc khai báo một giao diện phi generic ICanCreateICanCreate<T> kéo dài. Về cơ bản bạn muốn một mối quan hệ kiểu không thể diễn tả trong C# - và bất cứ khi nào điều đó xảy ra, bạn kết thúc với một giải pháp hơi khó chịu, nhưng có vẻ như bạn có thể cô lập sự xấu xí ở đây (tức là giữ nó trong một đĩa đơn) lớp học).

+0

Bạn sẽ nói gì được ưa thích nhất một trong hai? Tôi luôn tìm giải pháp thứ hai nếu tôi ở trong tình huống này, tin rằng đó là một giải pháp thanh lịch hơn. Nó có hay không quan trọng? – Razzie

+2

Có bất kỳ thành viên nào bạn có thể đưa vào giao diện không chung chung một cách hợp lý không? Nếu giao diện là * chỉ * phương thức Create, thì tôi sẽ gắn bó với đối tượng - giao diện không chung chung sẽ không thực sự cung cấp cho bạn bất cứ thứ gì. Trong các trường hợp khác, bạn có thể thoát khỏi chỉ với việc tham chiếu đến giao diện không chung chung mà bạn không biết đối số kiểu phù hợp, trong trường hợp đó cung cấp một lợi ích rõ ràng. –

+0

Rõ ràng, cảm ơn nhận xét! – Razzie

3

Điều thú vị, đây là một vấn đề mà được giải quyết trong C# 4.0:

public interface ICanCreate<out T> // covariant 
{ 
    T NewObject(); 
} 

public class Factory 
{ 
    private Dictionary<Type, ICanCreate<object>> mappings = new Dictionary<Type, ICanCreate<object>>(); 

    public void RegisterCreator<T>(ICanCreate<T> creator) where T:class 
    {    
     mappings[typeof(T)] = creator; 
    } 

    public T Create<T>() 
    {    
     ICanCreate<object> creator = mappings[typeof(T)]; 
     return (T) creator.NewObject(); // I do not think you can get rid of this cast 
    } 
} 
+0

'T' làm gì? – Svish

+0

@Svish: Nó đánh dấu T là biến thể. –

+0

Hm .. điều đó có nghĩa là gì? Bạn có liên kết có thêm thông tin về điều đó hay gì đó không? – Svish