接口中的自我引用

6
好的,下面是我想要做的事情。
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,则接口的所有实现者在其NotifyContained方法中必须使用IContainerObject,而不是它们实现的类的名称。
对于显而易见的原因,使用ImplementingType作为接口内容器的类型甚至更糟糕!
因此,我的问题是,我该怎么做才能使REPLACE_THIS表示实现接口的对象的类?
2个回答

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
如果您为T声明一个通用约束条件,就可以避免强制转换。 - Morten Mertner
哎呀,我刚刚注意到我的示例代码中有一个拼写错误,因为我注意到你为 IContainerObject 创建了一个空接口——我不小心打错了 IContainable,而不是 IContainer。这是否意味着你的 IContainer 接口可以被简单地删除? - Georges Oates Larsen
还有,类型转换也很有趣!谢谢 :) - Georges Oates Larsen

1

也许你已经知道了,但是如果只允许IContainableObjects作为T,那么你可以像这样声明你的类

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

    ...
}

有趣的解决方案!IContainableObject是一个可选接口--只适用于那些需要它的人,所以对我来说这不是一个可行的选择,但在任何其他情况下,看起来它会起作用 :) - Georges Oates Larsen

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接