接口中的自引用

时间:2012-05-19 20:29:21

标签: c# generics interface containers self-reference

好的,这就是我想做的事。

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.
    }
}

基本上,总结一下上面的例子,我有一个类型为T的通用包装类型。 我希望那个包装器类型能够通知它所包含的内容(包含它自己的副本!)如果包含的对象实现了一个特定的接口(这一点,我知道该怎么做)

但它变得棘手!为什么?好吧,因为容器泛型需要有一个类型。

还记得重要的一句吗?

如果REPLACE_THIS是IContainableObject,那么接口的所有实现者都必须使用IContainerObject,而不是NotifyContained方法中实现类的名称。

出于显而易见的原因,使用ImplementingType作为接口内容器的类型更加糟糕!

所以我的问题是,如何使REPLACE_THIS代表实现接口的对象的类?

2 个答案:

答案 0 :(得分: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;
    }
}

编辑:添加具有通用约束的版本

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;
    }
}

答案 1 :(得分:1)

也许您已经知道了,但如果只允许IContainableObjectsT,您可以像这样声明您的课程

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

    ...
}