2012-05-19 13 views
5

Được rồi, đây là những gì tôi muốn làm.Tự tham khảo trong giao diện

Class Container<T> 
{ 
    T contained; 
    public void ContainObject(T obj) 
    { 
     contained = obj; 
     if(/*Magical Code That Detects If T Implemtns IContainableObject*/) 
     { 
      IContainableObect c = (IContainableObject)obj; 
      c.NotifyContained(self); 
     } 
    } 
} 

interface IContainableObject 
{ 
    public void NotifyContained(Container<REPLACE_THIS>);//This line is important, see below after reading code. 
} 



Class ImplementingType : IContaiableObject 
{ 
    public Container<ImplementingType> MyContainer; 
    public void NotifyContained(Container<ImplmentingType> c) 
    { 
     MyContainer = c; 
    } 
} 




Class Main 
{ 
    public static void Main(args) 
    { 
     ImplementingType iObj = new ImplementingType(); 
     Container<ImplementingType> container = new Container(); 
     container.ContainObject(iObj); 
     //iObj.MyContainer should now be pointing to container. 
    } 
} 

Về cơ bản, tổng hợp các ví dụ trên, tôi có một loại wrapper chung của loại T. Tôi muốn rằng loại wrapper để thông báo cho bất cứ điều gì nó chứa mà nó đang được chứa (với một bản sao của bản thân mình !) NẾU đối tượng chứa thực hiện một giao diện cụ thể (bit này tôi biết cách làm)

Nhưng nó trở nên phức tạp! Tại sao? Vâng vì container chung cần phải có một loại.

Hãy nhớ rằng dòng quan trọng?

Nếu REPLACE_THIS là IContainableObject, thì tất cả người triển khai giao diện phải sử dụng IContainerObject, không phải tên của lớp triển khai trong phương thức NotifyContained của họ.

Sử dụng ImplementingType làm loại vùng chứa trong giao diện thậm chí còn tồi tệ hơn, vì những lý do hiển nhiên!

Vì vậy, câu hỏi của tôi là, tôi phải làm gì để làm cho REPLACE_THIS đại diện cho lớp của đối tượng đang triển khai giao diện?

Trả lời

4
class Container<T> 
{ 
    T contained; 
    public void ContainObject(T obj) 
    { 
     contained = obj; 
     var containable = obj as IContainableObject<T>; 
     if(containable != null) 
     { 
      containable.NotifyContained(this); 
     } 
    } 
} 

interface IContainableObject<T> 
{ 
    void NotifyContained(Container<T> c); 
} 

class ImplementingType : IContainableObject<ImplementingType> 
{ 
    public Container<ImplementingType> MyContainer; 
    public void NotifyContained(Container<ImplementingType> c) 
    { 
     MyContainer = c; 
    } 
} 

EDIT: thêm phiên bản với chế generic

interface IContainer<T> 
{ 
    void ContainObject(T obj); 
} 

class Container<T> : IContainer<T> where T : IContainableObject<T> 
{ 
    T contained; 

    public void ContainObject(T obj) 
    { 
     contained = obj; 
     contained.NotifyContained(this); 
    } 
} 

interface IContainableObject<T> 
{ 
    void NotifyContained(IContainer<T> c); 
} 

class ImplementingType : IContainableObject<ImplementingType> 
{ 
    public IContainer<ImplementingType> MyContainer; 

    public void NotifyContained(IContainer<ImplementingType> c) 
    { 
     Debug.WriteLine("notify contained"); 
     MyContainer = c; 
    } 
} 
+0

Cảm ơn bạn rất nhiều! Làm việc như một nét duyên dáng :) –

+1

Bạn có thể tránh quá trình truyền nếu bạn khai báo ràng buộc chung cho T. –

+0

Rất tiếc, tôi đã nhận thấy lỗi đánh máy trong mã ví dụ của tôi sau khi nhận thấy bạn đã tạo giao diện trống cho IContainerObject - Tôi đã vô tình gõ IContainer không thể IContainable. Điều này có nghĩa là giao diện IContainer của bạn có thể đơn giản bị xóa? –

1

Có lẽ bạn biết nó đã có, nhưng nếu chỉ IContainableObjects được phép như T bạn có thể khai báo lớp học của bạn như thế này

class Container<T> 
    where T : IContainableObject 
{ 
    public void ContainObject(T obj) 
    { 
     // Here you know that obj does always implement IContainableObject. 
     obj.NotifyContained(this); 
    } 

    ... 
} 
+0

Giải pháp thú vị! IContainableObject là một giao diện tùy chọn - Chỉ dành cho những người muốn nó, vì vậy đây không phải là một lựa chọn khả thi đối với tôi, nhưng trong bất kỳ trường hợp nào khác, có vẻ như nó sẽ hoạt động :) –